C++ многострочный строковый литерал
есть ли способ иметь многострочный простой текст, постоянные литералы в C++, à la Perl? Может быть, какой-то парсинг трюк с #include
ing файл? Я не могу придумать ни одного, но это было бы здорово. Я знаю, что это будет в C++0x.
7 ответов:
хорошо ... Что-то вроде того. Проще всего просто использовать тот факт, что соседние строковые литералы объединяются компилятором:
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.";
отступ не имеет значения, так как он не находится внутри кавычек.
вы также можете сделать это, пока вы заботитесь о том, чтобы избежать встроенной новой строки. В противном случае, как и мой первый ответ, не будет компилироваться:
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.";опять же, обратите внимание на эти обратные косые черты в конце каждой строки, они должны быть непосредственно перед строка заканчивается, они избегают новой строки в источнике, так что все действует так, как будто новой строки там не было. Вы не получаете новые строки в строке в местах, где у вас были обратные косые черты. С помощью этой формы вы, очевидно, не можете отступить текст, так как отступ станет частью строки, искажая ее случайными пробелами.
В C++11 у вас есть "сырые" строковые литералы. Вроде как здесь-текст в оболочках и скриптовых языках, таких как Python и Perl и 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";
все пробелы и отступы и новые строки в строке сохраняются.
Они также могут быть UTF-8/16/32 или wchar_t (с обычными префиксами).
Я должен отметить, что escape-последовательность, V0G0N, на самом деле не нужна здесь. Его наличие позволит поставить ) " внутри строки. Другими словами, Я мог бы поставить
"(by Prostetnic Vogon Jeltz; see p. 56/57)"
(обратите внимание на дополнительные кавычки), и строка выше все равно будет правильной. В противном случае я мог бы также использовать
const char * vogon_poem = R"( ... )";
парены только внутри кавычек по-прежнему необходимы.
#define MULTILINE(...) #__VA_ARGS__
Потребляет все между скобками.
Заменяет любое количество последовательных пробелов одним пробелом.
Это, наверное, удобный способ ввода нескольких строк с помощью макроса. Это работает только если кавычки и скобки сбалансированы и не содержат 'верхнем уровне' запятой:
#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);
скомпилированный с gcc 4.6 или g++ 4.6, это производит:
[[Using this trick(,) you don't need to use quotes. Though newlines and multiple white spaces will be replaced by a single whitespace.]]
отметим, что
,
не может быть в строке, если она не содержится в скобках или кавычках. Одинарные кавычки возможны, но создает предупреждения компилятора.Edit: как упоминается в комментариях,
#define MULTI_LINE_STRING(...) #__VA_ARGS__
позволяет использовать,
.
поскольку унция опыта стоит тонны теории, я попробовал небольшую тестовую программу для
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" ) // "1, \"2\" " };
скомпилировать этот фрагмент
cpp -P -std=c++11 filename
воспроизвести.секрет
#__VA_ARGS__
это__VA_ARGS__
не обрабатывает запятая. Так что вы можете передать его в строковый оператор. Начальные и конечные пробелы обрезаются, а пробелы (включая новые строки) между словами сжимаются до одного пробела. Скобки должны быть сбалансированы. Я думаю эти недостатки объясняют, почему конструкторы C++11, несмотря на#__VA_ARGS__
, увидел необходимость в необработанных строковых литералах.
просто чтобы немного прояснить комментарий @emsr в ответе @unwind, если вам не повезло иметь компилятор C++11 (скажем, GCC 4.2.1), и вы хотите встроить новые строки в строку (либо char*, либо строку класса), можно написать что-то вроде этого:
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.";
очень очевидно, правда, но короткий комментарий @emsr не выскочил на меня, когда я прочитал это в первый раз, поэтому мне пришлось открыть это для себя. Надеюсь, я сэкономил кому-то еще несколько минут.