为什么我从cin读取时转义字符不起作用?

40
(a)
(a)
string str = "Hello\nWorld";

当我打印 str 时,输出结果为:
Hello
World

(b)
(b)
string str;
cin >> str;      //given input as Hello\nWorld

当我打印str时,输出结果为:
Hello\nWorld

(a) 和 (b) 有什么区别?

在Linux上,您可以使用echo -e "Hello,\nWorld" | ./testprogram命令将转义字符转换为换行符,而不是传递给程序的文字\n - Davislor
7个回答

58

C++编译器在处理控制字符时有特定的规则 - 文档。如您所见,当您在字符串字面值中指定\n时,它将被编译器替换为换行符(ASCII码为0xa)。因此,您获得的不是两个符号\n,而是一个具有二进制代码0xa的符号(我假设您使用ASCII编码),该符号在打印输出时使控制台移至新行。当读取字符串时,编译器不会介入,您的字符串实际上包含符号\n


8
完全正确。转义码是源代码解析器的一个特性,而不是 C++ 字符串数据的一个特性。 - Euro Micelli
2
语言定义不需要对 ’\n’ 有任何特定的值要求。 - Pete Becker
1
@PeteBecker:答案说它给出的值是针对ASCII的,这几乎涵盖了所有现代SBCS系统。使用其他字符集的人将不得不自己找到适用的值。 - Ben Voigt
3
在Windows上,"\n"也是{0x0A, 0x00}。文件(或控制台)I/O会将其转换为0D 0A...但对于C++程序来说它只是一个。你可以有一个系统,其中'\n'是-2,但那不是ASCII系统。标准保证字符转义会被转换为执行字符集中相应的值。如果执行字符集是ASCII,那么'\n'==10,这是有保证的。 - Ben Voigt
2
@PeteBecker:LF是一个字符编码的名称。括号不是代码名称的一部分,它们表示附加信息。但我的主要观点是:'\n'始终只有一个字符。编译器不能将其转换为CR-LF对。如果执行字符集是ASCII,则一个字符\n必须是0A。如果执行字符集是EBCDIC,则显然会有所不同。但换行符转换与字符串字面量完全无关。 - Ben Voigt
显示剩余4条评论

14
当在字符串文字中指定时,"\n"将被翻译为匹配的ASCII代码(在Linux上为0x0a),并按原样存储。它不会被存储为反斜杠,后跟字面意义的n转义序列仅为您提供方便,以允许带有嵌入换行符的字符串文字。
另一方面,您的shell在终端中运行时不进行这种替换:它提交一个字面上的反斜杠和n,这将被打印出来。
要打印换行符,请输入换行符:
$ echo "Hello
 World" | ./your-program 

1
虽然echo的实现因计算机而异,但echo -e“hello \n world”是一个相当可靠的方法,可以将\n解释为换行符。如果不行,那么如果您的计算机上有printf,则保证printf“hello \n world \n”可以正常工作。 - BallpointBen
2
返回已翻译的文本:不是ASCII代码,而是“执行字符集”(字符编码)-几乎肯定不是ASCII(即使对于此字符,代码可能相同)。 - Tom Blodget
特别是,仍有一些计算机正在运行,执行字符集为EBCDIC,而'\n'与0x0a完全不同。 - Martin Bonner supports Monica
可能知道如何从终端输入文字换行是很有用的:在大多数终端中,按下Ctrl+V,然后再按Ctrl+J。 - mindriot
@BallpointBen,printf(命令行实用程序)是标准的,所以你很可能已经拥有它了(可能内置于shell中)。echo -e非常常见,但值得注意的是,Dash(Debian/Ubuntu的/bin/sh)对其不太友好。然后还有$'..'引用,可以处理C风格的转义字符。这不是标准的,因此dash也不支持它,但几乎所有其他shell都支持它。 - ilkkachu
在后一种情况下,请注意 std::cin >> str,其中 strstd::string,只从标准输入读取1个单词(以空格分隔的标记)。 - user202729

10

cout<<"Hello\nworld"中的字符串被编译器转换为已编译的字符串,其中转义代码被转换为字符,因此当执行cout函数时,不会看到两个字符"\n"的字符串,而是下一行字符的等效代码。

但是,cin在运行时获取每个键入字符的字符串,并且不会转换转义代码。因此,如果您想要转换这些转义代码,则需要使用替换函数。


6

cin不包括C++编译器。字符串字面量中的转义序列是C++词法分析器的一个特性,它是C++编译器的一部分。流基本上提供了来自操作系统的内容(它们可能会根据操作系统进行一些CRLF -> CR的翻译或类似的操作,但仅此而已)。


4

当我从cin读取时,为什么转义字符不起作用?

这是因为流读取器被定义成那样。在核心中,每个字符都被单独读取。只有更高级别的函数才会给这些字符提供额外的含义。

当编译器处理字符串字面值"Hello\nWorld"时,它的文件读取器也会传递相同的两个字符。只有C++编译器/解析器根据语言规则将它们转换为一个字符。


4
在编译代码中,字符字面量 '\n' 会被替换为实现特定的值,运行时系统会将其视为换行符。语言定义没有要求任何特定的值。
当从控制台或文件中读取输入时,传入的文本不会被编译,字符序列“\n”没有任何特殊含义,它只是两个字符。

3

字符串中的转义字符由编译器进行解释。序列\n由两个实际字符组成,在编译期间,编译器将其转换为单个换行符。当您在命令行中输入相同序列时,该序列不会以任何方式被解释,因此结果是您输入的确切两个字符。

如果您想要处理您的字符串并解释转义序列,则需要自己完成(或使用适当的库)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接