Есть ли способ иметь многострочные текстовые, константные литералы на С++, à la Perl? Может быть, какой-то синтаксический анализ с #include
с файлом? Я не могу думать об одном, но мальчик, это было бы хорошо. Я знаю, что это будет в С++ 0x.
Многострочный литерал строки С++
Ответ 1
Ну... Сорт. Самое простое - просто использовать тот факт, что смежные строковые литералы конкатенируются компилятором:
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 \ content. This works, but you can't indent.";
Опять же, обратите внимание на обратную косую черту в конце каждой строки, они должны быть немедленно перед завершением строки, они ускользают от новой строки в источнике, так что все действует так, как будто новой строки не было. Вы не получаете символы новой строки в строке в местах, где у вас были обратные косые черты. С помощью этой формы вы, очевидно, не можете отступать от текста, так как отступ становится частью строки, искажая ее случайными пробелами.
Ответ 2
В С++ 11 у вас есть строковые литералы. Похоже здесь - текст в оболочках и script языки, такие как 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"( ... )";
Параны внутри кавычек все еще нужны.
Ответ 3
#define MULTILINE(...) #__VA_ARGS__
Потребляет все между круглыми скобками.
Заменяет любое количество последовательных символов пробелов на одно пространство.
Ответ 4
Вероятно, удобным способом ввода многострочных строк является использование макросов. Это работает только в том случае, если кавычки и скобки сбалансированы и не содержат запятую "верхний уровень":
#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.]]
Обратите внимание, что ,
не может быть в строке, если она не содержится в круглых скобках или кавычках. Одинарные кавычки возможны, но создаются предупреждения компилятора.
Изменить: Как упоминалось в комментариях, #define MULTI_LINE_STRING(...) #__VA_ARGS__
позволяет использовать ,
.
Ответ 5
Вы можете просто сделать это:
const char *text = "This is my string it is "
"very long";
Ответ 6
Поскольку унция опыта стоит тонны теории, я пробовал небольшую тестовую программу для 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"
};
Скомпилируйте этот фрагмент с cpp -P -std=c++11 filename
для воспроизведения.
Тройка за #__VA_ARGS__
заключается в том, что __VA_ARGS__
не обрабатывает разделитель запятой. Поэтому вы можете передать его оператору стробирования. Верхние и конечные пробелы обрезаются, а пробелы (включая новые строки) между словами сжимаются до одного пробела. Скобки должны быть сбалансированы. Я думаю, что эти недостатки объясняют, почему дизайнеры С++ 11, несмотря на #__VA_ARGS__
, видели необходимость в строковых литералах строки.
Ответ 7
Просто, чтобы немного разъяснить комментарий @emsr в ответ @unwind, если кому-то не повезло иметь компилятор С++ 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 не выскочил на меня, когда я прочитал это в первый раз, поэтому мне пришлось открыть это для себя. Надеюсь, что несколько минут я спас другого человека.
Ответ 8
Вы также можете сделать это:
const char *longString = R""""(
This is
a very
long
string
)"""";