Почему объявления строковых литералов C / C ++ должны быть однострочными? - PullRequest
17 голосов
/ 22 июня 2010

Есть ли какая-либо конкретная причина, по которой многострочные строковые литералы, такие как следующие, не разрешены в C ++?

string script =
"
      Some
   Formatted
 String Literal
";

Я знаю, что многострочные строковые литералы могут быть созданы путем добавления обратной косой черты перед каждой новой строкой. Я пишу на языке программирования (похожем на C) и хотел бы позволить легко создавать многострочные строки (как в приведенном выше примере).

Есть ли какая-либо техническая причина избегать такого строкового литерала? В противном случае мне пришлось бы использовать строковый литерал, похожий на python, с тройной кавычкой (что я не хочу делать):

string script =
"""
      Some
   Formatted
 String Literal
""";

Почему объявления строковых литералов в C / C ++ должны быть однострочными?

Ответы [ 10 ]

30 голосов
/ 22 июня 2010

Краткий ответ: «потому что грамматика запрещает многострочные строковые литералы».Я не знаю, есть ли для этого веские причины, кроме исторических.

Конечно, есть способы обойти это.Вы можете использовать сращивание строк:

const char* script = "\
      Some\n\
   Formatted\n\
 String Literal\n\
";

Если \ появится как последний символ в строке, новая строка будет удалена во время предварительной обработки.

Или вы можете использовать строковый литералконкатенация:

const char* script = 
"      Some\n"
"   Formatted\n"
" String Literal\n";

Смежные строковые литералы объединяются во время предварительной обработки, поэтому они заканчиваются как строковый литерал во время компиляции.

При использовании любого метода строковый литерал заканчиваетсяесли бы было написано:

const char* script = "      Some\n   Formatted\n  String Literal\n";
15 голосов
/ 22 июня 2010

Нужно учитывать, что C был написан не как язык программирования "Applications", а как язык системного программирования.Не было бы неправильно сказать, что он был разработан специально для переписывания Unix.Имея это в виду, не было EMACS или VIM, и ваши пользовательские интерфейсы были последовательными терминалами.Многострочные строковые объявления кажутся немного бессмысленными в системе, в которой нет многострочного текстового редактора.Кроме того, манипуляции со строками не будут основной проблемой для тех, кто хочет написать ОС в данный конкретный момент времени.Традиционный набор инструментов сценариев UNIX, таких как AWK и SED (среди многих других), является свидетельством того факта, что они не использовали C для значительных манипуляций со строками.

Дополнительные соображения: это не было редкостью вв начале 70-х (когда был написан C), чтобы представить свои программы на PUNCH CARDS и вернуться на следующий день, чтобы получить их.Не потратил ли бы это дополнительное время на компиляцию программы с многострочными строковыми литералами?На самом деле, нет.На самом деле это может быть меньше работы для компилятора.Но ты все равно собирался вернуться на следующий день в большинстве случаев.Но никто, кто заполнял перфокарту, не собирался помещать большие объемы текста, которые не были нужны в их программах.

В современной среде, вероятно, нет причин не включать многострочные строковые литералы, кромепредпочтения дизайнера.Грамматически говоря, это, вероятно, проще, потому что вам не нужно учитывать перевод строки при разборе строкового литерала.

6 голосов
/ 22 июня 2010

Другие упомянули несколько отличных обходных путей, я просто хотел обратиться к причине .

Причина заключается просто в том, что C был создан в то время, когда обработка была на пределе, а компиляторы должны были быть простыми и максимально быстрыми. В наши дни, если C нужно обновить (я смотрю на тебя, C1X ), вполне возможно, что можно делать именно то, что ты хочешь. Это маловероятно, однако. Главным образом по историческим причинам; такое изменение может потребовать значительных переписываний компиляторов и поэтому, вероятно, будет отклонено.

4 голосов
/ 09 сентября 2011

В дополнение к существующим ответам, вы можете обойти это, используя необработанные строковые литералы C ++ 11 , например:

#include <iostream>
#include <string>

int main() {
   std::string str = R"(a
b)";
   std::cout << str;
}

/* Output:
a
b
*/

Живая демонстрация.


[n3290: 2.14.5/4]: [ Примечание: Новая строка исходного файла в литерале необработанной строки приводит к новой строке в результирующей строке выполнения -literal .При условии отсутствия пробелов в начале строк в следующем примере утверждение выполнится успешно:

const char *p = R"(a\
b
c)";
assert(std::strcmp(p, "a\\\nb\nc") == 0);

- конечная заметка ]

Хотя ненормативный, это примечание и пример, следующий за ним в [n3290: 2.14.5/5], служат дополнением к указанию в грамматике, что продукция r-char-sequence может содержать символы новой строки (тогда как продукция s-char-sequence, используемая для обычных строковых литералов, может не иметь).

3 голосов
/ 22 июня 2010

Препроцессор C работает построчно, но с лексическими токенами. Это означает, что препроцессор понимает, что "foo" является токеном. Однако, если бы C разрешил многострочные литералы, препроцессор был бы в затруднении. Рассмотрим:

"foo
#ifdef BAR
bar
#endif
baz"

Препроцессор не может связываться с внутренней частью токена - но он работает построчно. Так как же справиться с этим делом? Простое решение - просто полностью запретить многострочные строки.

2 голосов
/ 22 июня 2010

На самом деле, вы можете разбить его так:

string script =
"\n"
"      Some\n"
"   Formatted\n"
" String Literal\n";

Смежные строковые литералы объединяются компилятором.

1 голос
/ 22 июня 2010

Я пишу язык программирования (аналогично C) и хотел бы легко писать многострочные строки (например, в приведенном выше примере).

Нет причин, по которым вы не могли бы создать язык программирования, который бы допускал многострочные строки. Например, Vedit Macro Language (который является C-подобным языком сценариев для текстового редактора VEDIT) допускает многострочные строки, например:

Reg_Set(1,"
      Some
   Formatted
 String Literal
")

Вам решать, как определить синтаксис языка.

1 голос
/ 22 июня 2010

Строки могут лежать на нескольких строках, но каждая строка должна быть заключена в кавычки:

string script =
    "                \n"
    "       Some     \n"
    "    Formatted   \n"
    " String Literal ";
0 голосов
/ 13 февраля 2013

Литеральные объявления не должны быть однострочными.

GPUImage встроенный многострочный код шейдера. Оформить заказ в макросе SHADER_STRING.

0 голосов
/ 22 июня 2010

Вы также можете сделать:

string useMultiple =  "this" 
                      "is "
                      "a string in C."; 

Поместить один литерал за другим без каких-либо специальных символов.

...