Есть ли способ иметь многострочные текстовые, постоянные литералы в C++, à la Perl? Может быть, какой-то синтаксический анализ с #include
в файле? Я не могу думать об одном, но мальчик, это было бы хорошо. Я знаю, что это будет в C++ 0x.C++ многострочный строковый литерал
ответ
Ну ... Вроде. Проще всего использовать только тот факт, что смежные строковые литералы сцепляются компилятором:
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.";
Опять же, обратите внимание, эти обратные косые черты в конце каждой строки, то они должны быть непосредственно перед завершением линии, они убегают символ новой строки в источник, так что все действует так, как будто новой строки не было. Вы не получаете символы новой строки в строке в местах, где у вас были обратные косые черты. С этой формой вы, очевидно, не можете отступать от текста, так как отступ становится частью строки, искажая ее случайными пробелами.
Мне говорили в прошлом, что первый вариант может быть до реализации, однако мне еще предстоит найти компилятор, который не соблюдает этот синтаксис. –
@Jason: он не обязательно был частью компиляторов pre-C89, но он определен на C89 и поэтому поддерживается практически везде. –
Кроме того, если вы действительно хотите, чтобы строка, отформатированная на нескольких строках в C++ 98, просто заменила \ n на завершающее пространство на каждый цитируемый фрагмент строки. C++ 11 сырые литералы по-прежнему остаются моей любимой. – emsr
Вы можете просто сделать это:
const char *text = "This is my string it is "
"very long";
В 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"(...)";
в круглых скобках только внутри кавычек по-прежнему необходимы.
Это действительно то, что я хочу, способность избегать цитат, обратных косых черт, экранов и, тем не менее, появляются новые строки в реальной строке. Это удобно для встроенного кода (например, шейдеров или Lua). К сожалению, мы все еще не используем C++ - 0x. :-( – mlepage
Я сам рассматривал это для встроенных скриптов SQL и Python. Я надеялся на ваше счастье, если, возможно, gcc разрешил бы ему проходить в режиме C++ 98, но, увы, нет. – emsr
Это не компилируется для меня в Visual Studio 2012.Есть ли какие-либо вещи, которые должны быть установлены в проекте или файлах для включения? – jjxtra
вероятно удобный способ ввода строк многострочной помощи. Эта функция работает только MACRO, если котировки и круглые скобки сбалансированы, и он не содержит «верха уровня:
#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 или г ++ 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__
позволяет использовать ,
.
Для проекта, в котором я хотел включить некоторые фрагменты кода lua в C++, я закончил писать небольшой скрипт python, в который я ввел многострочные строки, и пусть это сгенерирует исходный файл C++. – bcmpinc
Идеально подходит для меня, добавив огромную многострочную строку с плавающей точкой из файла collada для модульного тестирования. Мне не нравилось размещать кавычки повсюду, мне нужно было скопировать и вставить решение. –
Вы можете использовать '#define MULTILINE (...) #__ VA_ARGS__', если вы хотите, чтобы ваша строка содержала запятые. – Simon
#define MULTILINE(...) #__VA_ARGS__
Потребляет все между круглыми скобками.
Заменяет любое количество последовательных пробельных символов на одно пространство.
Вы можете добавить '\ n', если вам нужны строки новой строки – Simon
Обратите внимание, что' \ '(и, следовательно,' \ n') копируется буквально, но '' 'преобразуется в' \ ''. Поэтому 'MULTILINE (1," 2 "\ 3)' дает '' 1, \ "2 \" \ 3 "'. –
@AndreasSpindler Котировки и обратные косые черты сбрасываются (дополнительными) обратными косыми чертами до тех пор, пока они появляются внутри символа символа строки или символа. Не уверен, в чем дело. Нельзя иметь непревзойденную цитату (двойную или одиночную), поэтому сокращения не работают или нечетное число из них в любом случае, что, вероятно, является самым большим недостатком. +1 в любом случае. «Реальные программисты» всегда используют сокращения в парах без промежуточной новой строки, поэтому баланс одиночных кавычек. – Potatoswatter
Просто для того, чтобы немного разъяснить комментарий @ emsr в ответе @ unwind, если кому-то не повезло, чтобы иметь компилятор C++ 11 (скажем, GCC 4.2.1), и хочется вставить строки в строку (или символ * или строка класса), можно написать что-то вроде этого:
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 в не выскочит на меня, когда я прочитал это в первый раз, так что я должен был открыть это для себя. Надеюсь, я спасал кого-то еще несколько минут.
Поскольку унция опыта стоит тонна теории, я попробовал немного тестовую программу для 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__
не обрабатывает разделитель запятой. Поэтому вы можете передать его оператору стробирования. Верхние и конечные пробелы обрезаются, а пробелы (включая новые строки) между словами сжимаются до одного пробела. Скобки должны быть сбалансированы. Я думаю, что эти недостатки объясняют, почему дизайнеры C++ 11, несмотря на #__VA_ARGS__
, увидели необходимость в строковых литералах.
Как правило, вы не хотите вставлять строковые литералы в код. Для I18N и L10N предпочтительнее помещать строковые литералы в файл конфигурации, который загружается во время выполнения. –
Существует достаточно случаев, когда размещение строковых литералов в код не является проблемой: если строка не используется для представления ее пользователю; то есть: инструкции SQL, имена файлов, имена ключей реестра, строки команд, которые должны быть выполнены, ... – mmmmmmmm
@Martin: Однако все же полезно знать. Например, я сделал это, чтобы разбить сложные регулярные выражения. – Boojum