我使用的是带有gcc 4.8.1的Linux x86_64。
代码:
#include <stdio.h>
int main(int argc, char *argv[])
{
int ch;
do
{
printf("ch : ");
ch = getchar(); //Q Why CTRL+M = 10 and not 13?
getchar();
printf("ch = %d\n\n", ch);
}while(ch != 'z');
return 0;
}
输出:
ch : ^N
ch = 14
ch :
ch = 10
ch :
ch = 10
ch : z
ch = 122
问题:
在上面的程序中,当我输入Ctrl+J
(换行符)时,它会吐出10,这确实是\n
的ASCII但是当我输入Ctrl+M
(回车符)时,它也会吐出10而不是13(ASCII值\r
)。
发生了什么事? \n
和\r
共享相同的ASCII值吗?那么哪个字符代表ASCII 13?
编辑:
$ uname -a
Linux Titanic 3.11.0-26-generic #45-Ubuntu SMP Tue Jul 15 04:02:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
答案 0 :(得分:4)
问题是终端驱动程序中启用了ICRNL
。这是tcsetattr(3)
手册页的一个片段,用于设置终端属性:
ICRNL
在输入时将回车转换为换行符(除非设置IGNCR
)。
要禁用ICRNL
,您可以在程序之前运行以下命令(或直接使用tcsetattr()
):
$ stty -icrnl
stty -a
可让您查看当前的终端设置。
请注意,上述操作会阻止 Enter 键正常工作(因为它会生成回车符,而终端驱动程序在将行发送到程序之前等待换行符终止该行)。您将不得不使用 Ctrl-J 。 :)
下面是关于为什么 Return 仍然在禁用IGNCR
的shell中工作的原因(至少在Bash中),以防你感兴趣:
Bash使用readline库来读取命令。在读取命令之前,readline将终端置于 noncanonical 模式,其中输入是无缓冲的(一旦输入字符,就可以一次读取一个字符)。因此,readline在输入后立即看到回车字符,并且恰好接受它作为行终止符。
需要非规范模式来实现花式线编辑,例如能够使用光标键移动光标并在命令中间插入文本。像ncurses这样的文本UI库也使用此模式。
当您的C程序运行时,终端处于规范模式,而终端驱动程序执行行缓冲(一次将输入发送到进程)。此模式仅具有基本行编辑(例如,支持删除)并且不解释光标键,这就是当您按下它们时屏幕上出现奇怪字符序列的原因。 (这些字符是光标键生成的terminal escape sequences,在此模式下可见。一个方便的实验命令是没有参数的普通cat
。)
通过ICANON
启用/禁用Canonical模式,这是一个与IGNCR
类似的选项。从shell试验它可能有点棘手,因为shell会在程序(如stty
)运行时设置并重置它。
答案 1 :(得分:0)
我不知道^ J键盘快捷键,但我愿意打赌如果你用固定字符(不是从终端读取)提供代码&#39; \ r&#39;和&#39; \ n&#39;您将获得正确的ASCII值。这意味着你的终端设置要像@alk所说的那样错,或者^ J没有做你认为它做的事情......