Многострочный литерал строки С++

Есть ли способ иметь многострочные текстовые, константные литералы на С++, à 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
)"""";