581 Stimmen

C++ mehrzeiliges String-Literal

Gibt es eine Möglichkeit, mehrzeilige Klartextliterale in C++ zu verwenden, wie in Perl? Vielleicht ein Parsing-Trick mit #include in einer Datei? Mir fällt keine ein, aber Junge, das wäre schön. Ich weiß, dass es in C++0x sein wird.

2 Stimmen

Im Allgemeinen sollten Sie keine Stringliterale in den Code einbetten. Für I18N und L10N ist es besser, String-Literale in eine Konfigurationsdatei zu schreiben, die zur Laufzeit geladen wird.

63 Stimmen

Es gibt genügend Fälle, in denen das Einfügen von String-Literalen in den Code kein Problem darstellt: wenn der String nicht verwendet wird, um ihn dem Benutzer darzustellen; d.h.: SQL-Anweisungen, Dateinamen, Namen von Registrierungsschlüsseln, auszuführende Befehlszeilen, ...

4 Stimmen

@Martin: Es kann aber trotzdem nützlich sein, das zu wissen. Ich habe es zum Beispiel gemacht, um komplexe Regexe aufzulösen.

767voto

unwind Punkte 377331

Na ja ... Irgendwie schon. Am einfachsten ist es, einfach die Tatsache zu nutzen, dass benachbarte String-Literale vom Compiler verkettet werden:

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

Die Einrückung spielt keine Rolle, da sie nicht innerhalb der Anführungszeichen steht.

Sie können dies auch tun, solange Sie darauf achten, den eingebetteten Zeilenumbruch zu vermeiden. Wenn Sie dies nicht tun, wie es in meiner ersten Antwort der Fall war, wird der Text nicht kompiliert:

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

Beachten Sie auch hier die Backslashes am Ende jeder Zeile. Sie müssen unmittelbar vor dem Zeilenende stehen, da sie den Zeilenumbruch im Quelltext umgehen, so dass sich alles so verhält, als ob der Zeilenumbruch nicht vorhanden wäre. Sie erhalten keine Zeilenumbrüche in der Zeichenkette an den Stellen, an denen Sie Backslashes hatten. Bei dieser Form können Sie den Text natürlich nicht einrücken, da die Einrückung dann Teil der Zeichenkette wird und diese mit zufälligen Leerzeichen durcheinander bringt.

38 Stimmen

@Jason: Es war nicht unbedingt ein Teil der Vor-C89-Compiler, aber es ist in C89 definiert und wird daher im Wesentlichen überall unterstützt.

4 Stimmen

Wenn Sie die Zeichenkette in C++98 wirklich auf mehreren Zeilen formatiert haben wollen, ersetzen Sie einfach \n für das abschließende Leerzeichen in jedem zitierten Zeichenfolgenfragment. C++11 rohe Literale sind immer noch mein Favorit.

3 Stimmen

@unwind Beachten Sie, dass der Zeilenumbruch am Ende der Quellzeile nicht Teil der Zeichenkette ist, sondern einfach übersprungen wird. Wenn Sie einen Zeilenumbruch als Teil der Zeichenkette wünschen, müssen Sie \n\ am Ende der Zeile.

639voto

emsr Punkte 14381

In C++11 haben Sie rohe String-Literale. Ähnlich wie here-text in Shells und Skriptsprachen wie Python, Perl und 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";

Alle Leerzeichen und Einrückungen sowie die Zeilenumbrüche in der Zeichenkette bleiben erhalten.

Diese können auch utf-8|16|32 oder wchar_t (mit den üblichen Präfixen) sein.

Ich sollte darauf hinweisen, dass die Escape-Sequenz, V0G0N, hier eigentlich nicht benötigt wird. Ihr Vorhandensein würde es ermöglichen, )" in die Zeichenkette einzufügen. Mit anderen Worten, ich hätte auch

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

(beachten Sie die zusätzlichen Anführungszeichen) und die obige Zeichenfolge wäre immer noch korrekt. Andernfalls hätte ich genauso gut verwenden können

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

Die Parens innerhalb der Anführungszeichen werden weiterhin benötigt.

37 Stimmen

Dies ist wirklich, was ich will, die Fähigkeit, Anführungszeichen, Backslash-Ns, Escapes zu vermeiden, und immer noch Zeilenumbrüche in der eigentlichen Zeichenfolge angezeigt werden. Das ist praktisch für eingebetteten Code (z.B. Shader oder Lua). Leider verwenden wir noch nicht alle C++-0x :-(

2 Stimmen

Ich selbst habe dies für eingebettete SQL- und Python-Skripte in Betracht gezogen. Ich hatte gehofft, für Ihr Interesse, wenn vielleicht gcc würde es durch in C++98-Modus gleiten lassen, aber, leider, nein.

0 Stimmen

Dies kompiliert nicht für mich in Visual Studio 2012. Gibt es irgendwelche Dinge, die auf das Projekt oder Dateien festgelegt werden müssen, um einzuschließen?

73voto

Raydelto Hernandez Punkte 1862

Sie können auch dies tun:

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

2 Stimmen

Danke, das ist großartig, funktioniert sogar in C. offensichtlich, char longString[] = R""""( This is a very long string )""""; funktioniert auch bei mir.

3 Stimmen

Beginnt und endet die Zeichenkette dabei mit einer neuen Zeile?

2 Stimmen

Es ist ein Rohstringliteral . Verfügbar seit C++11.

33voto

#define MULTILINE(...) #__VA_ARGS__
Verbraucht alles, was zwischen den Klammern steht.
Ersetzt eine beliebige Anzahl von aufeinanderfolgenden Leerzeichen durch ein einzelnes Leerzeichen.

1 Stimmen

Sie können hinzufügen \n wenn Sie Zeilenumbrüche benötigen

0 Stimmen

Beachten Sie, dass ` (and hence \n ) is copied literally, but "wird umgewandelt in \" . Also MULTILINE(1, "2" \3) ergibt "1, \"2\" \3" .

0 Stimmen

@AndreasSpindler Anführungszeichen und Backslashes werden durch (zusätzliche) Backslashes maskiert, sofern sie innerhalb einer Zeichenkette oder eines Zeichenliteral-Tokens erscheinen. Ich bin mir nicht sicher, worauf Sie hinauswollen. Es ist illegal, ein unangepasstes Anführungszeichen (doppelt oder einfach) zu haben, also funktionieren Kontraktionen nicht, oder eine ungerade Anzahl von ihnen sowieso, was wahrscheinlich der größte Nachteil ist. +1 sowieso. "Echte Programmierer" verwenden Kontraktionen immer paarweise und ohne dazwischenliegenden Zeilenumbruch, damit die einfachen Anführungszeichen ausgeglichen werden.

32voto

bcmpinc Punkte 2942

Ein wahrscheinlich bequemer Weg, mehrzeilige Zeichenfolgen einzugeben, ist die Verwendung von Makros. Dies funktioniert nur, wenn Anführungszeichen und Klammern ausgeglichen sind und keine Kommas der obersten Ebene enthalten sind:

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

Mit gcc 4.6 oder g++ 4.6 kompiliert, ergibt dies: [[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]

Beachten Sie, dass die , kann nicht in der Zeichenkette stehen, es sei denn, es ist in Klammern oder Anführungszeichen enthalten. Einfache Anführungszeichen sind möglich, führen aber zu Compiler-Warnungen.

Bearbeiten: Wie in den Kommentaren erwähnt, #define MULTI_LINE_STRING(...) #__VA_ARGS__ ermöglicht die Verwendung von , .

0 Stimmen

Für ein Projekt, bei dem ich einige Lua-Code-Schnipsel in C++ einbinden wollte, habe ich ein kleines Python-Skript geschrieben, in das ich die mehrzeiligen Strings eingegeben habe, und daraus eine C++-Quelldatei generieren lassen.

0 Stimmen

Perfekt für mich, das Hinzufügen eines riesigen mehrzeiligen Float-List-Strings aus einer Collada-Datei für Unit-Tests. Ich hatte keine Lust, überall Anführungszeichen zu setzen, ich brauchte eine Copy&Paste-Lösung.

9 Stimmen

Sie können verwenden #define MULTILINE(...) #__VA_ARGS__ wenn die Zeichenfolge Kommas enthalten soll.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X