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

Two distinct characters sharing same ASCII value in C

我正在使用 Linux x86_64 和 gcc 4.8.1。

代码:

#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 (回车符-return 字符)时它吐出 10 而不是 13(\r 的 ASCII 值)。

这是怎么回事? \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

我不知道 ^J 键盘快捷键,但我敢打赌,如果您使用固定字符(不是从终端读取)'\r' 和 '\n' 来输入代码您将获得正确的 ASCII 值。这意味着要么是你的终端设置像@alk 说的那样是错误的,要么 ^J 没有按照你的想法去做......

问题是在终端驱动程序中启用了 ICRNL。这是 tcsetattr(3) 的手册页中的一个片段,它在 C 中用于设置终端属性:

ICRNL Translate carriage return to newline on input (unless IGNCR is set).

要禁用ICRNL,您可以在程序前运行以下命令(或直接使用tcsetattr()):

$ stty -icrnl

stty -a 让您查看当前的终端设置。

请注意,上面的内容也会阻止您的 Enter 键正常工作(因为它会生成回车符 return,而终端驱动程序正在等待换行符在将它发送到您的程序之前终止该行)。您将不得不使用 Ctrl-J 代替。 :)

下面是关于为什么 Return 在禁用 IGNCR 的 shell 中仍然有效的切线(在 Bash 至少),如果你有兴趣:

Bash 使用 readline 库来读取命令。在读取命令之前,readline 将终端置于 noncanonical 模式,其中输入是无缓冲的(可以一次读取一个字符,只要键入一个字符)。因此,readline 会在键入时立即看到回车 return 字符,并且恰好将其作为行终止符接受。

需要非规范模式来实现精美的行编辑,例如能够使用光标键移动光标并在命令中间插入文本。文本 UI 库,如 ncurses 也使用此模式。

当您的 C 程序 运行s 时,终端处于 规范 模式,终端驱动程序执行行缓冲(将输入发送到进程一行一次)。这种模式只有基本的行编辑(例如,支持擦除)并且不解释光标键,这就是为什么当你按下它们时屏幕上会出现奇怪的字符序列。 (这些字符是由光标键生成的 terminal escape sequences,在这种模式下变得可见。一个方便的实验命令是没有参数的普通 cat。)

规范模式是 enabled/disabled 到 ICANON,这是一个选项,就像 IGNCR 一样。从 shell 中尝试它可能有点棘手,因为 shell 设置和重置它作为程序(如 stty)是 运行.