Подтвердить что ты не робот

С++: Существует ли стандартное определение конца строки в многострочной строковой константе?

Если у меня есть строка с несколькими строками С++ 11, такая как

R"""line 1
line 2
line3"""

Определяется ли какой-либо символ (ы), разделитель строк/разделитель состоит из?

4b9b3361

Ответ 1

Цель состоит в том, что строка новой строки в строчном литерале строки сопоставляется с одним '\n' символ. Это намерение не выражается так четко, как оно должно быть, что привело к некоторой путанице.

Цитаты относятся к стандарту ISO С++ 2011 года.

Во-первых, это свидетельство того, что оно сопоставляется с одним символом '\n'.

В примечании в параграфе 2.14.5 [lex.string] говорится:

[Примечание. Новая строка исходного файла в строковом литерале приводит к new-line в результате выполнения строкового литерала. Предполагая, что нет пробел в начале строк в следующем примере, утверждение будет успешным:

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

- примечание к концу]

Это ясно указывает, что новая строка сопоставляется с одним '\n' персонаж. Он также соответствует наблюдаемому поведению g++ 6.2.0 и clang++ 3.8.1 (тесты, выполненные в системе Linux с использованием исходных файлов с Unix-стиль и конец строки в стиле Windows).

Учитывая четко сформулированное намерение в примечании и поведение двух популярные компиляторы, я бы с уверенностью полагался на это - хотя это было бы интересно увидеть, как другие компиляторы действительно справляются с этим.

Однако, буквальное чтение нормативной формулировки стандарт может легко привести к другому выводу или, по крайней мере, к некоторой неопределенности.

Раздел 2.5 [lex.pptoken], пункт 3, говорит (выделено мной):

Между начальным и окончательным символами двойной кавычки raw string, любые преобразования, выполняемые в фазах 1 и 2 (триграфы, универсальные имена символов и сращивание строк)возвращаются; эта реверсия должна применяться до любого d- char, r- char или идентифицировать скобки.

Фазы перевода указаны в 2.2 [lex.phases]. В фазе 1:

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

Если мы предположим, что отображение физических символов исходного файла на базовый набор символов и введение новых символов "трансформации", мы могли бы разумно заключить, что, например, строка новой строки в середине строкового литерала в формате Windows исходный файл должен быть эквивалентен последовательности \r\n. (Я могу представить что полезно для кода, специфичного для Windows.)

(Эта интерпретация приводит к проблемам с системами, в которых индикатор конца строки не является последовательностью символов, например где каждая строка представляет собой запись фиксированной ширины. Такие системы редки в эти дни.)

Как "Приветствия и hth. - Alf" ответ указывает, что есть открытый Отчет о дефектах для этого вопроса. Он был представлен в 2013 году и еще не был решена.

Лично я считаю, что корень путаницы - это слово "любое", (курсив добавлен как раньше):

Между начальным и конечным символами двойной кавычки string, любые преобразования, выполняемые в фазах 1 и 2 (триграфы, универсальные имена символов и сращивание строк); это реверсия должна применяться до любого d- char, r- char или разграничения скобки указаны.

Несомненно, отображение физических символов исходного файла в основной набор символов источника можно разумно подумать о как преобразование. Предложение в скобках "(триграфы, универсальные имена символов и сращивание линий) ", как представляется, указать, какие преобразования должны быть возвращены, но либо пытается изменить значение слова "преобразования", (который стандарт официально не определяет) или противоречит использованию слова "любой".

Я предлагаю изменить слово "любое" на "определенное" явное намерение гораздо яснее:

Между начальным и конечным символами двойной кавычки строка, некоторые преобразования, выполняемые в фазах 1 и 2 (триграфы, имена универсальных символов и линейное сращивание) возвращаются; это реверсия должна применяться до любого d- char, r- char или разграничения скобки указаны.

В этой формулировке было бы более ясно, что "триграфы, универсальные имена символов и линейное сращивание "являются единственными преобразования, которые должны быть возвращены. (Не все сделано в фазах перевода 1 и 2 возвращается только те конкретные перечисленные преобразования.)

Ответ 2

Стандарт, похоже, указывает, что:

R"""line 1
line 2
line3"""

эквивалентно:

"line 1\nline 2\nline3"

От 2.14.5 Строковые литералы стандарта С++ 11:

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

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

-end note]

5 [Пример: необработанная строка

R"a(
)\
a"
)a"

эквивалентно "\n)\\\na\"\n".

Ответ 3

Примечание: вопрос существенно изменился, поскольку ответы были опубликованы. Остается только половина, а именно чистый аспект С++. Сетевой фокус в этом ответе касается исходного вопроса "отправка многострочной строки на сервер с четко определенными требованиями к концу строки". Я вообще не преследую эволюцию вопроса.

Внутри программы стандарт С++ для новой строки \n. Это также используется для новой строки в исходном литерале. Для сырых литералов нет специального соглашения.

Обычно \n сопоставляется с линией перевода ASCII, которая является значением 10.

Я не уверен, что он отображает в EBCDIC, но вы можете проверить это при необходимости.

Однако на моем прохождении кажется, что большинство протоколов используют возврат каретки ASCII плюс перевод строки, т.е. 13 с последующим 10. Это иногда называют CRLF, после аббревиатур ASCII CR для возврата каретки и LF для перевода строки. Когда экраны С++ сопоставляются с ASCII, это просто \r\n в С++.

Вам необходимо соблюдать требования протокола, который вы используете.

Для обычного файла/потока i/o стандартная библиотека С++ заботится о отображении внутреннего \n в любом соглашении, которое использует среда хоста. Это называется текстовым режимом, в отличие от двоичного режима, когда отображение не выполняется.

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


Активная проблема с этим, отчет о дефекте основного языка # 1655 "Окончания строк в строковых литералах строки", представленный Майком Миллером 2013 -04-26, где он спрашивает,

" предполагается, что, например, CRLF в источнике строкового литерала должен быть представлен как символ новой строки или как исходные символы?

Так как значения окончания строки различаются в зависимости от кодировки исходного файла и, учитывая, что в некоторых файловых системах кодировка окончаний строк отсутствует, но вместо строк в качестве записей ясно, что намерение состоит не в том, чтобы представлять файл содержимое as-is – так как это невозможно сделать во всех случаях. Но насколько я вижу, этот DR еще не разрешен.