两个不同的字符在C中共享相同的ASCII值

时间:2015-03-30 11:51:40

标签: c ascii carriage-return xterm linefeed

我使用的是带有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

2 个答案:

答案 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没有做你认为它做的事情......