C ++:多行字符串常量中是否有行尾的标准定义?

时间:2016-10-05 23:54:20

标签: c++ c++11 portability

如果我有一个多行字符串C ++ 11字符串常量,如

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

是否定义了行终止符/分隔符由哪些字符组成?

3 个答案:

答案 0 :(得分:27)

意图是原始字符串文字中的换行符映射到单个字符串 '\n'字符。这种意图并没有像它那样清楚地表达出来 应该是,这导致了一些混乱。

引用符合2011 ISO C ++标准。

首先,这里有证据表明它映射到单个'\n'字符。

第2.14.5节[lex.string]第4段中的注释说:

  

[注意:原始字符串文字中的源文件换行符会产生一个   生成的执行 string-literal 中的换行符。假设没有   在下面的例子中,行的开头是空格   断言将成功:

    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段说(强调补充):

  

在初始和最终双引号字符之间   在第1阶段和第2阶段执行的原始字符串,任何转换   (三字符,通用字符名称和行拼接)   被还原;此回复应在任何 d-char 之前适用,    r-char ,或识别分隔括号。

翻译阶段在2.2 [lex.phases]中指定。在第1阶段:

  

物理源文件字符映射在一个   实现定义的方式,基本源字符集   (引入行尾指标的换行符)if   必要的。

如果我们假设物理源文件字符的映射到 基本字符集和新行字符的介绍 " 转换"我们可能会合理地得出结论,例如, Windows格式的原始字符串文字中间的换行符 源文件应该等同于\r\n序列。 (我能想象 这对Windows特定的代码很有用。)

(这种解释确实会导致系统出现问题 例如,行尾指示符不是字符序列 其中每一行都是固定宽度的记录。这种系统很少见 这些天。)

作为"Cheers and hth. - Alf"'s answer 指出,有一个开放的 Defect Report 对于这个问题。它于2013年提交,尚未提交 解决。

就个人而言,我认为混淆的根源是“#34;任何" (重点如前所述):

  

在raw的初始和最终双引号字符之间   字符串,在第1阶段和第2阶段执行的任何转换(trigraphs,   恢复通用字符名称和行拼接;这个   在任何 d-char r-char 或分隔之前应该应用reversion   括号被识别出来。

当然是物理源文件字符到的映射 可以合理地考虑基本源字符集 作为转型。带括号的条款"(三字符, 通用字符名称和行拼接)"似乎是有意的 指定要还原哪些转换,但是 要么试图改变单词的含义"转换" (标准没有正式定义)或与使用相矛盾 单词" any"。

我建议更改单词" any"到某些"某些"会表达 明显的意图更明确:

  

在raw的初始和最终双引号字符之间   字符串,在阶段1和2中执行的某些转换(trigraphs,   恢复通用字符名称和行拼接;这个   在任何 d-char r-char 或分隔之前应该应用reversion   括号被识别出来。

这个措辞会让人更加清楚"三字符, 通用字符名称和行拼接"是唯一的 要还原的转换。 (并非一切都完成了 在翻译阶段1和2被还原,只是那些具体的 列出的转换。)

答案 1 :(得分:16)

该标准似乎表明:

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

相当于:

"line 1\nline 2\nline3"

来自C ++ 11标准的 2.14.5字符串文字

  

4 [注意:原始字符串文字中的源文件换行符会在生成的执行字符串文字中产生换行符。假设在以下示例中的行的开头没有空格,则断言将成功:

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

- 结束记录]

     

5 [示例:原始字符串

R"a(
)\
a"
)a"
     

相当于"\n)\\\na\"\n"

答案 2 :(得分:9)

注意:自回答发布以来,问题已发生重大变化。只剩下一半,即纯C ++方面。本回答中的网络焦点解决了原始问题的“将多行字符串发送到具有明确定义的行尾要求的服务器”。我不追求一般的问题进化。

在程序内部,换行的C ++标准是\n。这也用于原始文字中的换行符。原始文字没有特殊约定。

通常\n映射到ASCII换行符,即值10。

我不确定它在EBCDIC中的映射是什么,但如果需要,你可以检查一下。

然而,在线上,我的印象是大多数协议使用ASCII回车加换行,即13后跟10.这有时称为 CRLF ,在ASCII缩写CR后回车和LF用于换行。当C ++转义符映射到ASCII时,这只是C ++中的\r\n

您需要遵守您正在使用的协议的要求。

对于普通文件/流i / o,C ++标准库负责将内部\n映射到主机环境使用的任何约定。这称为文本模式,而二进制模式则不执行映射。

对于标准库未涵盖的网络i / o,应用程序代码必须直接或通过某些库函数自行完成。

有一个活动问题关于这个,core language defect report #1655“原始字符串文字中的行结尾”,由迈克米勒2013-04-26提交,他在那里问道,

  

是否打算将原始字符串文字来源中的CRLF表示为换行符或原始字符?

由于行结束值因原始文件的编码而异,并且考虑到在某些文件系统中不是行结尾的编码,而是作为记录的行,很明显意图不是按原样表示文件内容 - 因为在所有情况下都不可能这样做。但据我所知,这个DR还没有解决。