从控制台使用getc读取\r(回车符)和\n(换行符)的区别?

35

我正在编写一个函数,基本上是等待用户按“Enter”键,然后执行某些操作。我在测试时发现下面的代码可以工作:

#include <stdio.h>

int main()
{
        int x = getc(stdin);
        if (x == '\n') {
                printf("carriage return");
                printf("\n");
        }
        else {
                printf("missed it");
                printf("\n");
        }
}

我有一个问题,一开始尝试的是这样做:if (x == '\r'),但在测试时,程序没有捕捉到我按回车键。 '\n' 似乎对应于我从控制台敲击回车键。有人能解释一下区别吗?此外,确认一下,将其写成 if... == "\n" 是指字符字符串文字吗?也就是说,用户必须从控制台输入"\n",对吗?


相关:https://dev59.com/E0nSa4cB1Zd3GeqPLSIt - Mysticial
1
C语言对单引号和双引号的字面量都应用转义字符,因此"\n"是一个长度为2的字符串,第一个字符是ASCII码10(\n本身),第二个字符是ASCII NUL(空终止符)。 - toriningen
1
希望您不介意标题的修改,这样可以更容易地搜索到它。 - user166390
1
在 C 语言中,你不能使用 == 来测试字符串的相等性,必须使用 strcmp 或类似函数。char *s1, *s2; if (s1 == s2) {...} 只会检查 s1s2 是否指向同一块内存区域,而不管实际内存内容。 - toriningen
如果您的标准输入以文本模式打开,则无论\n在执行字符集中表示什么,以及平台如何序列化换行符,您的应用程序始终会看到\n作为换行符。 - Kerrek SB
4个回答

61

\n是换行字符,而\r则是回车符。它们之间的区别在于使用方式不同。Windows使用\r\n表示按下了回车键,而Linux和Unix使用\n表示按下了回车键。

因此,我会始终使用\n,因为它被所有系统使用;而if (x == '\n')是测试字符相等的正确方法。


18

'\n'代表换行符,“\r”则代表回车符。不同的操作系统会以不同的方式处理换行符,例如:

Windows

期望一个换行符是由两个字符组成的,即 '\r\n'。

Linux\Unix和现代Mac OS

使用单个 '\n' 作为换行符。

Classic Mac OS

使用单个 '\r' 作为换行符。

基本上,像if (x == '\n')这样的语句目前被所有现代操作系统所使用。


Mac根据版本而异。[换行符] (http://en.wikipedia.org/wiki/Newline) - Jesse Good
4
我猜你指的是'\r'换行符在经典的Mac OS系统中使用,因为现代的Mac OS X系统是基于UNIX的,使用'\n'换行符。 - toriningen

4
有几个抽象级别可以表示换行——编程语言运行时、文本编辑器和操作系统。CR(回车)和LF(换行)是ASCII中定义的两个控制字符。其他一些字符编码也可能定义“换行”字符。任何键盘上的Enter键都传达着“到下一行开头”的意思。键盘决定如何将Enter键映射到其对应的控制字符或字符。有些键盘也区分Enter键和Return键-让Enter键成为换行,Return键成为回车。在标准的ANSI键盘上,只有Enter键,它被映射到ASCII中的一个回车字符(13)。因此,这就是设备发送到操作系统的实际内容。但是,不同的操作系统决定以不同的方式解释Enter键。因此,在类Unix系统中,任何回车符都会在转交输入的程序之前转换为一个换行符(ASCII中的10)。而在Windows上,一个CR会被翻译成两个字符-CR后跟LF。但是,您可以将输入流设置为原始模式,在这种情况下,程序可以获得键盘实际发送的内容。现在编辑器开始发挥作用了。当编辑器以原始模式从stdin接收到CR时,它知道CR对应于键盘上的Enter键(对键盘的假设),并且应该在屏幕上显示一个新行。在原始模式下,它应该调用写入系统调用以输出CR + LF。如果输出流不在原始模式下,则文本编辑器应输出特定于操作系统的序列,例如Linux上的LF。
最后,语言运行时也可以以自己的方式解释新行。例如,C标准说,在文本模式下写入文件时,“\n”会被透明地转换为系统使用的本机换行符,这可能比一个字符更长。在文本模式下读取时,本机换行符会被重新转换为“\n”。在二进制模式下,不执行任何转换,并且由“\n”生成的内部表示直接输出。请注意,“\n”和“\r”是表示LF和CR的语言特定字符,它们在类似C的语言中很受欢迎。但并不是每种语言都必须使用此符号。
对于您的第二个问题,“\n”是'\n'后跟一个'\0'终止符。无法从控制台输入'\0'。

3
还要记住,如果您输入了25个字符并按下回车键,则第一个getc在您键入所有25个字符并按下回车键之前不会返回。按时间顺序读取每个键入的字符需要特定于平台的代码。因此,最好通过将fgets执行到一个字符串中,删除换行符,并将输入行整体处理来读取整行内容。

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