Aufteilen von C ++ - Zeichenfolgen in mehrere Zeilen (Codesyntax, keine Analyse)

77

Nicht zu verwechseln mit dem Teilen einer Zeichenfolge, z. B.:
Teilen einer Zeichenfolge in C ++?

Ich bin etwas verwirrt darüber, wie man einen String in C ++ in mehrere Zeilen aufteilt.

Das klingt nach einer einfachen Frage, aber nehmen Sie das folgende Beispiel:

#include <iostream>
#include <string>
main() {
  //Gives error
  std::string my_val ="Hello world, this is an overly long string to have" +
    " on just one line";
  std::cout << "My Val is : " << my_val << std::endl;

  //Gives error
  std::string my_val ="Hello world, this is an overly long string to have" &
    " on just one line";  
  std::cout << "My Val is : " << my_val << std::endl;
}

Mir ist klar, dass ich die std::string append()Methode verwenden könnte, aber ich habe mich gefragt, ob es eine kürzere / elegantere (z. B. pythonähnliche, obwohl offensichtlich dreifache Anführungszeichen usw. in c ++ nicht unterstützt werden) Methode gibt, um Zeichenfolgen in c ++ aus Gründen der Übersichtlichkeit in mehrere Zeilen aufzuteilen der Lesbarkeit.

Ein Ort, an dem dies besonders wünschenswert wäre, ist, wenn Sie lange Zeichenfolgenliterale an eine Funktion (z. B. einen Satz) übergeben.

Jason R. Mick
quelle
2
Hier ist ein interessanter Leckerbissen: Dem C ++ - Lexer ist es eigentlich egal, wie viele Anführungszeichen Sie mit nur zwei Ausnahmen vor und nach einem String setzen. Die Anzahl der verwendeten Anführungszeichen muss ungerade sein und auf beiden Seiten übereinstimmen. """"" This is a valid string and will be parsed """"". Diesen Zeichenfolgen sind jedoch keine besonderen Eigenschaften zugeordnet. Sie verhalten sich einfach wie einfache Anführungszeichen.
Thomas Anthony
Interessanter Dank für das Teilen ... gibt es dafür einen nützlichen Zweck? Möglicherweise können Sie dies als subtiles Tag für verschiedene Gruppen von Zeichenfolgen in einem Code für die externe Analyse durch Perl / Bash / Python-Skripte verwenden. Das ist ungefähr alles, woran ich jetzt denken kann. :)
Jason R. Mick
@ThomasAnthony Das passiert nur, weil es die Anführungszeichen am Ende als eine Reihe leerer Zeichenfolgen behandelt und sie miteinander verkettet - es ist keine Funktion, es ist Standard-C / C ++
texasflood

Antworten:

126

Legen Sie nichts zwischen die Saiten. Ein Teil der C ++ - Lexierungsphase besteht darin, benachbarte Zeichenfolgenliterale (auch über Zeilenumbrüche und Kommentare) zu einem einzigen Literal zu kombinieren.

#include <iostream>
#include <string>
main() {
  std::string my_val ="Hello world, this is an overly long string to have" 
    " on just one line";
  std::cout << "My Val is : " << my_val << std::endl;
}

Beachten Sie, dass Sie, wenn Sie eine neue Zeile im Literal möchten, diese selbst hinzufügen müssen:

#include <iostream>
#include <string>
main() {
  std::string my_val ="This string gets displayed over\n" 
    "two lines when sent to cout.";
  std::cout << "My Val is : " << my_val << std::endl;
}

Wenn Sie eine #defineGanzzahlkonstante d in das Literal mischen möchten , müssen Sie einige Makros verwenden:

#include <iostream>
using namespace std;

#define TWO 2
#define XSTRINGIFY(s) #s
#define STRINGIFY(s) XSTRINGIFY(s)

int main(int argc, char* argv[])
{
    std::cout << "abc"   // Outputs "abc2DEF"
        STRINGIFY(TWO)
        "DEF" << endl;
    std::cout << "abc"   // Outputs "abcTWODEF"
        XSTRINGIFY(TWO) 
        "DEF" << endl;
}

Aufgrund der Funktionsweise des Stringify-Prozessoroperators gibt es einige Verrücktheiten. Sie benötigen also zwei Makroebenen, um den tatsächlichen Wert von TWOin ein String-Literal umzuwandeln .

Finsternis
quelle
Können Sie andere Elemente wie eine int-Konstante einmischen? Wenn nicht, wie füge ich diese hinzu?
Jason R. Mick
@ Jason: Was meinst du mit dem Einmischen einer int-Konstante?
Eclipse
my_function (arg_1, arg_2, "Hallo Welt, dieser String ist" ZWEI "Zeilen lang!");
Jason R. Mick
4
Das Kombinieren von Zeichenfolgenliteralen ist ein tatsächlicher Teil der lexikalischen Phase (nicht des Vorprozessors), da eine solche Zeichenfolgenaufteilung als Teil der Sprache definiert ist.
Martin York
1
@ Jason, aus Ihrer Folgefrage geht hervor, dass Sie so etwas wie das STRINGIFYobige Makro benötigen .
Eclipse
10

Sind sie beide wörtlich? Trennen von zwei Stringliterale mit Leerzeichen ist die gleiche wie Verkettung: "abc" "123"ist dieselbe wie "abc123". Dies gilt sowohl für Straight C als auch für C ++.

mkb
quelle
7

Ich weiß nicht, ob es sich um eine Erweiterung in GCC handelt oder ob es sich um eine Standarderweiterung handelt, aber es scheint, dass Sie ein Zeichenfolgenliteral fortsetzen können, indem Sie die Zeile mit einem Backslash beenden (genau wie die meisten Arten von Zeilen in diesem Manor in C ++ erweitert werden können). zB ein Makro, das mehrere Zeilen umfasst).

#include <iostream>
#include <string>

int main ()
{
    std::string str = "hello world\
    this seems to work";

    std::cout << str;
    return 0;
}
rmeador
quelle
4
Diese wörtliche Syntax enthält einige Leerzeichen zwischen worldundthis
SingleNegationElimination
@TokenMacGuy: In der Tat, das hatte ich nicht bemerkt. Einfach zu beheben, wenn Sie die zweite (und die folgenden) Zeilen ganz nach links verschieben. Aber das würde das Erscheinungsbild Ihrer Einrückung wirklich beeinträchtigen.
Rmeador
Ja, das war mein ursprünglicher Ansatz, aber ich habe ihn aufgrund der Einrückungs- / Abstandsprobleme bei @ SingleNegationElimination-Konturen aufgegeben. Gut zu bemerken.
Jason R. Mick