C++ multiline chaîne littérale

Existe-t-il un moyen d'avoir des littéraux constants en texte brut multiligne en C++, à la Perl? Peut-être un truc d'analyse avec #include ing un fichier? Je ne peux pas penser à une, mais le garçon, ce serait sympa. Je sais que ce sera en C++0x.

327
demandé sur kokociel 2009-07-16 10:55:57

7 réponses

Eh bien ... En quelque sorte. Le plus simple est d'utiliser simplement 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 elle n'est pas à l'intérieur des 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 =
  "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.";

Encore une fois, notez ces barres obliques inverses à la fin de chaque ligne, elles doivent être immédiatement avant la fin de la ligne, elles s'échappent le retour à la ligne dans la source, de sorte que tout agit comme si le retour à la ligne n'était pas là. Vous n'obtenez pas de nouvelles lignes dans la chaîne aux endroits où vous avez eu des barres obliques inverses. Avec ce formulaire, vous ne pouvez évidemment pas indenter le texte car l'indentation deviendrait alors une partie de la chaîne, la garblant d'espaces aléatoires.

480
répondu unwind 2017-02-15 12:01:13

En C++11, Vous avez des littéraux de chaîne bruts. Un peu comme ici-texte dans les shells 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 et l'indentation et les sauts de ligne dans la chaîne sont conservés.

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

Je dois souligner que la séquence d'échappement, V0G0N, n'est pas réellement nécessaire ici. Sa présence permettrait de mettre )" à l'intérieur de la chaîne. En d'autres termes, je pourrais avoir mettre

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

(notez les guillemets supplémentaires) et la chaîne ci-dessus serait toujours correcte. Sinon, je pourrais tout aussi bien avoir utilisé

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

Les parens juste à l'intérieur des guillemets sont toujours nécessaires.

271
répondu emsr 2017-05-10 02:34:28

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

25
répondu Zlatan Stanojević 2013-01-12 13:08:46

Un moyen probablement pratique d'entrer des chaînes multilignes est d'utiliser des macros. cela ne fonctionne que si les guillemets et les parenthèses sont équilibrés et qu'ils ne contiennent pas de virgule de niveau supérieur:

#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, sauf s'il est contenu entre parenthèses ou entre guillemets. Les guillemets simples sont possibles, mais créent des avertissements du compilateur.

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

22
répondu bcmpinc 2013-11-19 18:40:12

Vous pouvez simplement faire ceci:

const char *text = "This is my string it is "
     "very long";
12
répondu Eric 2013-04-21 07:33:00

Depuis une once d'expérience vaut mieux qu'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.

L'astuce derrière #__VA_ARGS__ est que __VA_ARGS__ ne traite pas le séparateur de virgules. Ainsi, vous pouvez le passer à l'opérateur de stringisation. Les espaces de début et de fin sont coupés, et les espaces (y compris les sauts de ligne) entre les mots sont compressés en 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 vu le besoin de littéraux de chaîne brute.

9
répondu Andreas Spindler 2013-09-11 13:21:10

Juste pour élucider un peu le commentaire de @emsr dans la réponse de @unwind, si l'on n'a pas la chance d'avoir un compilateur C++11 (disons GCC 4.2.1), et que l'on veut intégrer les nouvelles lignes dans la chaîne (char * ou Class string), 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.";

Très évident, vrai, mais le court commentaire de @ emsr ne m'a pas sauté dessus quand j'ai lu ceci la première fois, alors j'ai dû le découvrir par moi-même. J'espère que j'ai sauvé quelqu'un d'autre quelques minutes.

4
répondu CXJ 2013-01-15 22:01:24