Esiste un modo per avere letterali costanti a più righe in C ++, alla Perl? Forse qualche trucco di analisi con l' #include
ing di un file? Non riesco a pensarne uno, ma ragazzo, sarebbe carino. So che sarà in C ++ 0x.
Esiste un modo per avere letterali costanti a più righe in C ++, alla Perl? Forse qualche trucco di analisi con l' #include
ing di un file? Non riesco a pensarne uno, ma ragazzo, sarebbe carino. So che sarà in C ++ 0x.
Risposte:
Bene ... In un certo senso. Il più semplice è semplicemente usare il fatto che i letterali stringa 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 ha importanza, poiché non è racchiuso tra virgolette.
Puoi anche farlo, purché ti occupi di sfuggire alla newline incorporata. In caso contrario, come ha fatto la mia prima risposta, non verrà compilato:
const char * text2 = "Qui, invece, sono impazzito \ e lascia che letteralmente si estenda su più righe, \ senza preoccuparsi di citare ogni riga \ soddisfare. Funziona, ma non puoi rientrare. ";
Ancora una volta, nota quelle barre rovesciate alla fine di ogni riga, devono essere immediatamente prima della fine della riga, stanno scappando dalla nuova riga nella fonte, in modo che tutto si comporti come se la nuova riga non fosse lì. Non si ottengono newline nella stringa nei punti in cui si sono verificate barre rovesciate. Con questo modulo, ovviamente, non puoi indentare il testo poiché l'indentazione diventerebbe parte della stringa, confondendola con spazi casuali.
In C ++ 11 hai letterali stringa grezzi. Un po 'come qui-testo in shell e linguaggi di script come Python, 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, i rientri e le nuove righe nella stringa vengono conservati.
Questi possono anche essere utf-8 | 16 | 32 o wchar_t (con i soliti prefissi).
Vorrei sottolineare che la sequenza di escape, V0G0N, non è effettivamente necessaria qui. La sua presenza consentirebbe di inserire) "all'interno della stringa. In altre parole, avrei potuto mettere
"(by Prostetnic Vogon Jeltz; see p. 56/57)"
(nota le virgolette extra) e la stringa sopra sarebbe ancora corretta. Altrimenti avrei potuto usare altrettanto bene
const char * vogon_poem = R"( ... )";
Le parentesi appena dentro le virgolette sono ancora necessarie.
#if 0
... #endif
per commentare blocchi di codice. Anche i nidi.
#define MULTILINE(...) #__VA_ARGS__
Consuma tutto tra parentesi.
Sostituisce un numero qualsiasi di spazi bianchi consecutivi di un singolo spazio.
\n
se hai bisogno di nuove righe
` (and hence
\ n ) is copied literally, but
"` viene convertito in \"
. Quindi MULTILINE(1, "2" \3)
cede "1, \"2\" \3"
.
Un modo probabilmente conveniente per inserire stringhe multilinea è usare le macro. Funziona solo se le virgolette e le parentesi sono bilanciate e non contiene virgole di "livello superiore":
#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 g ++ 4.6, 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.]]
Nota che ,
non può essere nella stringa, a meno che non sia racchiuso tra parentesi o virgolette. Le virgolette singole sono possibili, ma creano avvisi del compilatore.
Modifica: come menzionato nei commenti, #define MULTI_LINE_STRING(...) #__VA_ARGS__
consente l'utilizzo di ,
.
#define MULTILINE(...) #__VA_ARGS__
se si desidera che la stringa contenga virgole.
\n
e \r
), il che è utile per alcuni casi e fatale per altri.
Puoi anche fare questo:
const char *longString = R""""(
This is
a very
long
string
)"""";
char longString[] = R""""( This is a very long string )"""";
funziona anche per me.
Poiché un'oncia di esperienza vale un sacco 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
per riprodurre.
Il trucco dietro #__VA_ARGS__
è che __VA_ARGS__
non elabora il separatore di virgola. Quindi puoi passarlo all'operatore di stringere. Gli spazi iniziali e finali vengono tagliati e gli spazi (comprese le nuove linee) tra le parole vengono compressi in un unico spazio. Le parentesi devono essere bilanciate. Penso che queste carenze spieghino perché i progettisti di C ++ 11, nonostante #__VA_ARGS__
, abbiano visto la necessità di letterali di stringa grezzi.
Giusto per chiarire un po 'il commento di @ emsr nella risposta di @ unwind, se uno non è abbastanza fortunato da avere un compilatore C ++ 11 (diciamo GCC 4.2.1), e si vuole incorporare le nuove righe nella stringa (o char * o 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 ovvio, vero, ma il breve commento di @ emsr non è saltato fuori da me quando l'ho letto la prima volta, quindi ho dovuto scoprirlo da solo. Spero di aver salvato qualcun altro qualche minuto.
// C++11.
std::string index_html=R"html(
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VIPSDK MONITOR</title>
<meta http-equiv="refresh" content="10">
</head>
<style type="text/css">
</style>
</html>
)html";
Opzione 1. Utilizzando la libreria boost, è possibile dichiarare la stringa come di seguito
const boost::string_view helpText = "This is very long help text.\n"
"Also more text is here\n"
"And here\n"
// Pass help text here
setHelpText(helpText);
Opzione 2. Se boost non è disponibile nel progetto, è possibile utilizzare std :: string_view () nel C ++ moderno.