HOWTO · C++

Dichiarare la stringa multilinea in C++

In questo articolo viene illustrato come dichiarare una stringa su più linee in C++

In questa pagina

Le stringhe multilinea sono importanti quando lavori con testi lunghi o vuoi preservare la formattazione nel codice sorgente. C++ non offre un tipo dedicato alle stringhe multilinea, ma mette a disposizione diversi modi per costruirne una: letterali stringa adiacenti, letterali stringa raw, giunzione con barra rovesciata a fine riga e stringificazione del preprocessore. Le tecniche differiscono soprattutto nel fatto che le interruzioni di riga nel sorgente diventino o meno newline nel valore.

Questa guida esamina ogni approccio con esempi eseguibili e si conclude con un confronto che ti aiuterà a scegliere quello più adatto al tuo codice.

Costruisci una stringa multilinea con letterali stringa adiacenti

Quando il compilatore incontra due o più letterali stringa tra doppie virgolette uno accanto all’altro, separati solo da spazi bianchi, li concatena in un unico valore in fase di compilazione. Suddividere un letterale su più righe del sorgente è puramente una scelta di formattazione: nessun newline viene aggiunto al valore se non scrivi tu stesso \n, e gli spazi devono essere inclusi esplicitamente dove le parole devono restare separate.

Esegui questo esempio; il codice e il testo visibile dell’output restano in inglese:

#include <iostream>
#include <string>

int main() {
  std::string message =
      "I love"
      " getting my doubts solved"
      " by the help of Delft Stack Tutorials.";

  std::cout << message << std::endl;
  return 0;
}
I love getting my doubts solved by the help of Delft Stack Tutorials.

La concatenazione di letterali adiacenti funziona allo stesso modo quando la destinazione è un const char * — un puntatore a un letterale di sola lettura — anziché un oggetto std::string:

#include <cstdio>

int main() {
  const char *lines =
      "Line 1 "
      "Line 2 "
      "Line 3";

  std::printf("%s\n", lines);
  return 0;
}
Line 1 Line 2 Line 3

Scegli std::string quando il testo verrà modificato o passato ad API che lavorano con le stringhe; un const char * è adatto a testo statico che viene solo stampato o esaminato.

Preserva le interruzioni di riga con i letterali stringa raw

C++11 ha introdotto i letterali stringa raw, che consentono alle interruzioni di riga fisiche di restare all’interno del letterale stesso. Tutto ciò che si trova tra R"( e )" — inclusi newline, indentazione, virgolette e barre rovesciate — diventa parte del valore alla lettera, quindi non servono sequenze di escape. Il codice e il testo visibile dell’output dell’esempio restano in inglese:

#include <iostream>
#include <string>

int main() {
  std::string page = R"(I love
getting my doubts solved
by the help of Delft Stack Tutorials.)";

  std::cout << page << std::endl;
  return 0;
}
I love
getting my doubts solved
by the help of Delft Stack Tutorials.

Poiché il contenuto viene copiato alla lettera, fai attenzione a due dettagli: un newline digitato subito dopo l’apertura R"( viene memorizzato nel valore e anche l’indentazione prima delle righe successive viene preservata. Se il testo contiene la sequenza )", scegli un delimitatore personalizzato come R"tag(...)tag" — il marcatore di chiusura richiede quindi il tag, così un semplice )" all’interno del testo resta innocuo.

Continua un letterale stringa con la barra rovesciata a fine riga

Una barra rovesciata come ultimo carattere di una riga del sorgente unisce quella riga alla successiva prima della compilazione. All’interno di un letterale stringa, ciò consente al letterale di estendersi su più righe del sorgente, ma l’interruzione di riga unita viene rimossa: non produce un newline nel valore. Questa è la differenza fondamentale rispetto alla sequenza di escape \n, che invece aggiunge un newline. Il codice e il testo visibile dell’output dell’esempio restano in inglese:

#include <cstdio>

int main() {
  const char *text =
      "First line\n"
      "Second line\n\
      Third line\n";

  std::printf("%s", text);
  return 0;
}
First line
Second line
      Third line

L’output mostra entrambi i meccanismi all’opera: ogni \n scrive un newline, mentre la giunzione con la barra rovesciata unisce solo le righe del sorgente — e gli spazi iniziali sulla riga continuata diventano caratteri reali nel valore. Questa sensibilità agli spazi bianchi è il principale pericolo: l’indentazione digitata per leggibilità finisce nella stringa e qualsiasi carattere dopo la barra rovesciata, anche uno spazio, interrompe la giunzione. Usa questa tecnica solo dove controlli pienamente il layout circostante.

Comprendi i limiti della stringificazione delle macro

Una macro variadica può trasformare i suoi argomenti in un letterale stringa con l’operatore di stringificazione, come in #define MULTILINE_STRING(...) #__VA_ARGS__. Passando testo distribuito su più righe si ottiene un unico letterale tra virgolette, ma il preprocessore normalizza ogni sequenza di spazi bianchi, inclusi i newline, riducendola a un singolo spazio. Il codice e il testo visibile dell’output dell’esempio restano in inglese:

#include <iostream>
#include <string>

#define MULTILINE_STRING(...) #__VA_ARGS__

int main() {
  std::string message = MULTILINE_STRING(
      I love getting my doubts solved by the help of Delft Stack Tutorials.);

  std::cout << message << std::endl;
  return 0;
}
I love getting my doubts solved by the help of Delft Stack Tutorials.

Questo rende la stringificazione delle macro un’opzione vincolata, non uno strumento generalista per le stringhe multilinea. Non può preservare le interruzioni di riga, il testo degli argomenti viene tokenizzato anziché trattato come contenuto della stringa (quindi punteggiatura imprevista può produrre risultati sorprendenti) e il codice basato su macro è più difficile da leggere e da sottoporre a debug. Ricorri a questa tecnica solo quando il codice guidato dal preprocessore deve davvero trasformare token in testo.

Scegli la tecnica giusta per le stringhe multilinea

  • I letterali stringa raw sono la scelta predefinita quando interruzioni di riga, indentazione o caratteri come \ e " devono sopravvivere alla lettera nel valore — ideali per blocchi di testo incorporati, JSON, SQL o espressioni regolari.
  • I letterali stringa adiacenti offrono un controllo preciso sul valore mantenendo corte le righe del sorgente; ogni spazio e ogni \n è esplicito, quindi non si insinua nulla di involontario.
  • La giunzione con barra rovesciata a fine riga è fragile e sensibile all’indentazione; sopravvive soprattutto nel codice legacy e nelle definizioni di macro, dove è ancora necessaria per continuare una definizione su più righe.
  • La stringificazione delle macro si adatta solo a codice che fa ampio uso del preprocessore e deve davvero convertire token in testo.

Per un valore che si estende davvero su più righe, usa un letterale stringa raw. Per un valore lungo su una sola riga formattato su più righe del sorgente, i letterali adiacenti sono la scelta più chiara — e si abbinano naturalmente sia a std::string sia a un const char *.