Domanda

C'è un modo per avere più linee di testo semplice, letterali costanti in C ++, à la Perl? Forse qualche trucco analisi con #includeing un file? Non riesco a pensare a una sola, ma il ragazzo, che sarebbe bello. So che sarà in C ++ 0x.

È stato utile?

Soluzione

Beh ... o meno. Il metodo più semplice è usare solo il fatto che stringhe letterali adiacenti sono concatenati dal compilatore:

const char *text =
  "This text is pretty long, but will be "
  "concatenated into just a single string. "
  "The disadvantage is that you have to quote "
  "each part, and newlines must be literal as "
  "usual.";

Il rientro non importa, dato che non è dentro le virgolette.

È anche possibile fare questo, a patto che si prende cura di sfuggire al ritorno a capo incorporato. In caso contrario, come la mia prima risposta ha fatto, non verrà compilato:

const char *text2 =
  "Here, on the other hand, I've gone crazy \
and really let the literal span several lines, \
without bothering with quoting each line's \
content. This works, but you can't indent.";

Ancora una volta, si noti tali barre rovesciate alla fine di ogni riga, devono essere immediatamente prima della linea termina, fuggono la nuova riga nella sorgente, in modo che tutto si comporta come se la nuova riga non c'era. Non si ottiene a capo nella stringa nelle posizioni in cui si aveva backslash. Con questo modulo, ovviamente non si può far rientrare il testo in quanto il rientro sarebbe poi diventata parte della stringa, garbling con spazi casuali.

Altri suggerimenti

in C ++ 11 si dispone di stringhe letterali prime. Un po 'come qui-testo in conchiglie e linguaggi di scripting come Python e Perl e Ruby.

const char * vogon_poem = R"V0G0N(
             O freddled gruntbuggly thy micturations are to me
                 As plured gabbleblochits on a lurgid bee.
              Groop, I implore thee my foonting turlingdromes.   
           And hooptiously drangle me with crinkly bindlewurdles,
Or I will rend thee in the gobberwarts with my blurlecruncheon, see if I don't.

                (by Prostetnic Vogon Jeltz; see p. 56/57)
)V0G0N";

Tutti gli spazi e l'indentazione e le nuove righe nella stringa sono conservati.

Questi possono anche essere utf-8 | 16 |. 32 o wchar_t (con i soliti prefissi)

Tengo a precisare che la sequenza di escape, V0G0N, non è effettivamente necessario qui. La sua presenza avrebbe permesso di mettere)" all'interno della stringa. In altre parole, avrei potuto mettere

                "(by Prostetnic Vogon Jeltz; see p. 56/57)"

(nota citazioni in più) e la stringa di cui sopra sarebbe ancora corrette. In caso contrario, ho potuto solo così ho usato

const char * vogon_poem = R"( ... )";

Le parentesi appena dentro le virgolette sono ancora necessari.

#define MULTILINE(...) #__VA_ARGS__
Consuma tutto tra le parentesi.
Sostituisce qualsiasi numero di spazi successivi da un singolo spazio.

Un probabilmente modo conveniente per immettere stringhe multilinea è quello di utilizzare macro di. Questo funziona solo se le citazioni e le parentesi sono equilibrate e non contiene 'top level' virgola di:

#define MULTI_LINE_STRING(a) #a
const char *text = MULTI_LINE_STRING(
  Using this trick(,) you don't need to use quotes.
  Though newlines and     multiple     white   spaces
  will be replaced by a single whitespace.
);
printf("[[%s]]\n",text);

compilato con GCC 4.6 o 4.6 g ++, questo produce: [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]

Si noti che il , non può essere nella stringa, a meno che non è contenuta all'interno di parentesi o virgolette. virgolette singole è possibile, ma crea gli avvisi del compilatore.

Modifica:. Come accennato nei commenti, #define MULTI_LINE_STRING(...) #__VA_ARGS__ consente l'utilizzo di ,

Si può solo fare questo:

const char *text = "This is my string it is "
     "very long";

Dal momento che un briciolo di esperienza vale una tonnellata di teoria, ho provato un piccolo programma di test per MULTILINE:

#define MULTILINE(...) #__VA_ARGS__

const char *mstr[] =
{
    MULTILINE(1, 2, 3),       // "1, 2, 3"
    MULTILINE(1,2,3),         // "1,2,3"
    MULTILINE(1 , 2 , 3),     // "1 , 2 , 3"
    MULTILINE( 1 , 2 , 3 ),   // "1 , 2 , 3"
    MULTILINE((1,  2,  3)),   // "(1,  2,  3)"
    MULTILINE(1
              2
              3),             // "1 2 3"
    MULTILINE(1\n2\n3\n),     // "1\n2\n3\n"
    MULTILINE(1\n
              2\n
              3\n),           // "1\n 2\n 3\n"
    MULTILINE(1, "2" \3)      // "1, \"2\" \3"
};

Compila questo frammento con cpp -P -std=c++11 filename di riprodursi.

Il trucco dietro #__VA_ARGS__ è che __VA_ARGS__ non elabora il separatore virgola. Così si può passare all'operatore stringizing. Spazi iniziali e finali sono tagliati, struttura (includendo i fine riga) tra le parole sono compressi in un singolo spazio poi. Le parentesi devono essere bilanciati. Credo che queste lacune spiegano perché i progettisti di C ++ 11, nonostante #__VA_ARGS__, ha visto la necessità di stringhe letterali prime.

Tanto per chiarire un po 'sul commento di @ EMSR in risposta @ di rilassarsi, se non si è abbastanza fortunati da avere un compilatore C ++ 11 (dire GCC 4.2.1), e vuole incorporare le nuove righe nella stringa ( o char * o di una stringa di classe), si può scrivere qualcosa del genere:

const char *text =
  "This text is pretty long, but will be\n"
  "concatenated into just a single string.\n"
  "The disadvantage is that you have to quote\n"
  "each part, and newlines must be literal as\n"
  "usual.";

molto evidente, è vero, ma @ breve commento di EMSR non saltare fuori di me quando ho letto la prima volta, ho avuto modo di scoprire questo per me stesso. Speriamo, ho salvato qualcun altro in pochi minuti.

È anche possibile fare questo:

const char *longString = R""""(
This is 
a very 
long 
string
)"""";
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top