web-dev-qa-db-fra.com

Littéral de chaîne multiligne C ++

Est-il possible d'avoir du texte brut multiligne, des littéraux constants en C++, à la Perl? Peut-être que quelques astuces d'analyse avec #includeing un fichier? Je ne peux pas en penser à un, mais bon sang, ce serait bien. Je sais que ce sera en C++ 0x.

368
rlbond

Eh bien ... en quelque sorte. Le plus simple consiste simplement à utiliser le fait que les littéraux de chaîne adjacents sont concaténés par le compilateur:

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.";

L'indentation n'a pas d'importance, car ce n'est pas dans les guillemets.

Vous pouvez également le faire tant que vous prenez soin d'échapper à la nouvelle ligne intégrée. Ne pas le faire, comme ma première réponse l'a fait, ne compilera pas:

 const char * text2 = 
 "Ici, par contre, je suis devenu fou\
 et ai laissé le littéral couvrir plusieurs lignes,\
 sans se soucier de citer le contenu de chaque ligne. Ceci fonctionne, mais vous ne pouvez pas mettre en retrait. "; 

Encore une fois, notez ces barres obliques inverses à la fin de chaque ligne, elles doivent être juste avant la fin de la ligne, elles échappent à la nouvelle ligne dans le source, de sorte que tout se passe comme si la nouvelle ligne n'existait pas. Vous ne recevez pas de nouvelles lignes dans la chaîne aux emplacements où vous avez eu des barres obliques inverses. Avec ce formulaire, vous ne pouvez évidemment pas mettre le texte en retrait car l’indentation ferait alors partie de la chaîne, le gargarisant avec des espaces aléatoires.

530
unwind

En C++ 11, vous avez des littéraux de chaîne bruts. Un peu comme ici-texte dans les shell et les langages de script comme Python et Perl et 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";

Tous les espaces, les indentations et les nouvelles lignes de la chaîne sont préservés.

Ceux-ci peuvent également être utf-8 | 16 | 32 ou wchar_t (avec les préfixes habituels).

Je tiens à souligner que la séquence d'échappement V0G0N n'est pas réellement nécessaire ici. Sa présence permettrait de mettre) "dans la ficelle. En d’autres termes, j’aurais pu mettre

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

(notez les guillemets supplémentaires) et la chaîne ci-dessus serait toujours correcte. Sinon, j'aurais tout aussi bien pu utiliser

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

Les parenthèses juste à l'intérieur des guillemets sont toujours nécessaires.

340
emsr

#define MULTILINE(...) #__VA_ARGS__
Consomme tout entre les parenthèses.
Remplace un nombre quelconque de caractères d'espacement consécutifs par un seul espace.

26
Zlatan Stanojević

Un moyen probablement pratique d'entrer des chaînes multilignes consiste à utiliser des macros. Cela ne fonctionne que si les guillemets et les parenthèses sont équilibrés et qu'il ne contient pas de virgule 'top level':

#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);

Compilé avec gcc 4.6 ou g ++ 4.6, cela produit: [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]

Notez que le , ne peut pas être dans la chaîne, à moins qu’il ne soit entre parenthèses ou entre guillemets. Les guillemets simples sont possibles, mais créent des avertissements pour le compilateur.

Edit: Comme mentionné dans les commentaires, #define MULTI_LINE_STRING(...) #__VA_ARGS__ permet l'utilisation de ,.

24
bcmpinc

Vous pouvez simplement faire ceci:

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

Puisqu'une once d'expérience vaut une tonne de théorie, j'ai essayé un petit programme de test pour 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"
};

Compilez ce fragment avec cpp -P -std=c++11 filename pour le reproduire.

Le truc derrière #__VA_ARGS__ est que __VA_ARGS__ ne traite pas le séparateur de virgule. Vous pouvez donc le transmettre à l'opérateur de stringing. Les espaces de début et de fin sont supprimés, puis les espaces (y compris les nouvelles lignes) entre les mots sont compressés dans un seul espace. Les parenthèses doivent être équilibrées. Je pense que ces lacunes expliquent pourquoi les concepteurs de C++ 11, malgré #__VA_ARGS__, ont compris le besoin de littéraux de chaîne bruts.

9
Andreas Spindler

Juste pour clarifier un peu le commentaire de @ emsr dans la réponse de @ undind, si on n'a pas la chance d'avoir un compilateur C++ 11 (disons GCC 4.2.1), et si on veut incorporer les nouvelles lignes dans la chaîne (soit char * ou une chaîne de classe), on peut écrire quelque chose comme ceci:

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.";

C'est évident, c'est vrai, mais le bref commentaire de @ emsr ne m'a pas échappé lorsque j'ai lu ceci la première fois, alors j'ai dû le découvrir moi-même. J'espère que j'ai sauvé quelqu'un d'autre quelques minutes.

7
CXJ

Vous pouvez aussi faire ceci:

const char *longString = R""""(
This is 
a very 
long 
string
)"""";
5
Raydelto Hernandez