HOWTO · C++
Mehrzeilige Zeichenkette in C++ deklarieren
Dieser Artikel demonstriert, wie man eine mehrzeilige Zeichenkette in C++ deklariert
Auf dieser Seite
Mehrzeilige Strings sind wichtig, wenn Sie mit längeren Texten arbeiten oder die Formatierung im Quellcode erhalten möchten. C++ hat keinen eigenen Typ für mehrzeilige Strings, bietet aber mehrere Möglichkeiten, einen zu erstellen: nebeneinander stehende String-Literale, Raw-String-Literale, die Zeilenverbindung per Backslash und die Stringification durch den Präprozessor. Die Techniken unterscheiden sich vor allem darin, ob Zeilenumbrüche im Quelltext zu Zeilenumbrüchen im Wert werden.
Diese Anleitung erläutert jeden Ansatz mit ausführbaren Beispielen und schließt mit einem Vergleich, damit Sie die passende Technik für Ihren Code wählen können.
Mehrzeiligen String mit nebeneinander stehenden String-Literalen erstellen
Wenn der Compiler zwei oder mehr in doppelten Anführungszeichen stehende String-Literale sieht, die nur durch Leerraum voneinander getrennt sind, verkettet er sie zur Kompilierzeit zu einem einzigen Wert. Ein Literal über mehrere Quellzeilen zu verteilen ist reine Formatierung — dem Wert wird kein Zeilenumbruch hinzugefügt, es sei denn, Sie schreiben selbst \n, und Leerzeichen müssen explizit dort stehen, wo Wörter getrennt bleiben sollen.
Führen Sie dieses Beispiel aus:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <iostream>
#include <string>
int main() {
std::string message =
"I love"
" getting my doubts solved"
" by the help of Delft Stack Tutorials.";
std::cout << message << std::endl;
return 0;
}
I love getting my doubts solved by the help of Delft Stack Tutorials.
Die Verkettung benachbarter Literale funktioniert genauso, wenn das Ziel ein const char * ist — ein schreibgeschützter Zeiger auf das Literal — und kein std::string-Objekt:
#include <cstdio>
int main() {
const char *lines =
"Line 1 "
"Line 2 "
"Line 3";
std::printf("%s\n", lines);
return 0;
}
Line 1 Line 2 Line 3
Wählen Sie std::string, wenn der Text verändert oder an string-verarbeitende APIs übergeben werden soll; ein const char * eignet sich für statischen Text, der nur ausgegeben oder geprüft wird.
Zeilenumbrüche mit Raw-String-Literalen erhalten
C++11 führte Raw-String-Literale ein, mit denen physische Zeilenumbrüche innerhalb des Literals selbst stehen können. Alles zwischen R"( und )" — einschließlich Zeilenumbrüchen, Einrückungen, Anführungszeichen und Backslashes — wird wörtlich Teil des Werts, sodass keine Escape-Sequenzen nötig sind:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <iostream>
#include <string>
int main() {
std::string page = R"(I love
getting my doubts solved
by the help of Delft Stack Tutorials.)";
std::cout << page << std::endl;
return 0;
}
I love
getting my doubts solved
by the help of Delft Stack Tutorials.
Da der Inhalt wörtlich übernommen wird, sollten Sie zwei Details beachten: Ein Zeilenumbruch direkt nach dem öffnenden R"( wird im Wert gespeichert, und die Einrückung vor Folgezeilen wird ebenfalls übernommen. Enthält Ihr Text einmal die Folge )", wählen Sie ein eigenes Trennzeichen wie R"tag(...)tag" — die schließende Markierung verlangt dann das Tag, sodass ein einfaches )" im Text harmlos bleibt.
String-Literal per Backslash-Zeilenverbindung fortsetzen
Ein Backslash als allerletztes Zeichen einer Quellzeile verbindet diese Zeile vor der Kompilierung mit der nächsten. Innerhalb eines String-Literals kann das Literal so über mehrere Quellzeilen laufen, doch der verbundene Zeilenumbruch wird entfernt — er erzeugt keinen Zeilenumbruch im Wert. Das ist der entscheidende Unterschied zur Escape-Sequenz \n, die tatsächlich einen Zeilenumbruch einfügt:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <cstdio>
int main() {
const char *text =
"First line\n"
"Second line\n\
Third line\n";
std::printf("%s", text);
return 0;
}
First line
Second line
Third line
Die Ausgabe zeigt beide Mechanismen im Zusammenspiel: Jedes \n schreibt einen Zeilenumbruch, während die Backslash-Verbindung nur die Quellzeilen zusammenführt — und die führenden Leerzeichen der fortgesetzten Zeile werden zu echten Zeichen im Wert. Diese Leerraum-Empfindlichkeit ist die größte Gefahr: Eine zur Lesbarkeit eingetippte Einrückung landet im String, und jedes Zeichen nach dem Backslash, sogar ein Leerzeichen, unterbricht die Verbindung. Setzen Sie diese Technik nur dort ein, wo Sie das umgebende Layout vollständig kontrollieren.
Die Grenzen der Makro-Stringification verstehen
Ein variadisches Makro kann seine Argumente mit dem Stringizing-Operator in ein String-Literal verwandeln, etwa #define MULTILINE_STRING(...) #__VA_ARGS__. Übergeben Sie Text, der über mehrere Zeilen verteilt ist, entsteht ein einziges Literal in Anführungszeichen — doch der Präprozessor reduziert jede Folge von Leerraum, einschließlich Zeilenumbrüchen, auf ein einzelnes Leerzeichen:
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
#include <iostream>
#include <string>
#define MULTILINE_STRING(...) #__VA_ARGS__
int main() {
std::string message = MULTILINE_STRING(
I love getting my doubts solved by the help of Delft Stack Tutorials.);
std::cout << message << std::endl;
return 0;
}
I love getting my doubts solved by the help of Delft Stack Tutorials.
Damit ist die Makro-Stringification eine Option für Sonderfälle, kein universelles Werkzeug für mehrzeilige Strings. Sie kann Zeilenumbrüche nicht erhalten, der Argumenttext wird tokenisiert statt als String-Inhalt behandelt (verirrte Satzzeichen können daher überraschende Ergebnisse liefern), und makrobasierter Code lässt sich schwerer lesen und debuggen. Greifen Sie nur dann darauf zurück, wenn präprozessorgesteuerter Code Token wirklich in Text umwandeln muss.
Die passende Technik für mehrzeilige Strings wählen
- Raw-String-Literale sind die Standardwahl, wenn Zeilenumbrüche, Einrückungen oder Zeichen wie
\und"wörtlich im Wert erhalten bleiben sollen — ideal für eingebettete Textblöcke, JSON, SQL oder reguläre Ausdrücke. - Nebeneinander stehende String-Literale geben präzise Kontrolle über den Wert und halten die Quellzeilen kurz; jedes Leerzeichen und jedes
\nist explizit, sodass nichts Unbeabsichtigtes hineinrutscht. - Die Backslash-Zeilenverbindung ist fragil und einrückungsempfindlich; sie überlebt vor allem in Legacy-Code und in Makrodefinitionen, wo sie nach wie vor nötig ist, um eine Definition über Zeilen fortzusetzen.
- Makro-Stringification passt nur zu stark präprozessorlastigem Code, der Token wirklich in Text umwandeln muss.
Für einen Wert, der sich wirklich über mehrere Zeilen erstreckt, verwenden Sie ein Raw-String-Literal. Für einen langen einzeiligen Wert, der im Quelltext formatiert wird, sind nebeneinander stehende Literale am klarsten — und sie lassen sich natürlich sowohl mit std::string als auch mit einem const char * kombinieren.