如何从键盘(运行 Linux)向 ac 程序发送 CR(即 ascii 13)?另外,为什么我必须发送两次 EOF 才能终止该程序?

如何从键盘(运行 Linux)向 ac 程序发送 CR(即 ascii 13)?另外,为什么我必须发送两次 EOF 才能终止该程序?

我读到过Ctrl-J发送 '\n',Ctrl-M发送 '\r' 和Ctrl-D发送 EOF,但这要么是错误的,要么就是我根本不明白发生了什么。这个简单的程序说明了:

const size_t SIZE = 100;

int main()
{
    char str[SIZE];
    printf("Enter string: ");
    size_t len = 0;
    char ch;
    while ((ch = getchar()) != '\r' && ch != '\n' && ch != EOF && len < SIZE -1)
    {
        str[len++] = ch;
        printf("ch is %i\n",ch);
    }
    printf("ch is %i\n",ch);
    str[len] = '\0';
    printf("%s\n",str);
    
    return 0;
}

当我输入:hello(Ctrl-j)时,输出正是我所期望的:

ch is 104
ch is 101
ch is 108
ch is 108
ch is 111
ch is 10
hello

但是当我输入:hello(Ctrl-m)时输出完全相同 - 即最后一个ch仍然是10,而不是我期望的13。

当我输入:hello(Ctrl-d)时,输出在“ch is 111”('o')后面的行首停止:

ch is 101
ch is 108
ch is 108
ch is 111

并等待,直到我第二次按下 Ctrl-d 之后它完成:

ch is -1
hello

或者,如果我按的是-或,而不是第二个Ctrl- 。在这种情况下,它以DCtrlJEnter

[blank line]
ch is 10
hello

丢失 -1 并打印 10 作为 '\n'。

我已经在运行 Arch Linux 的台式机和运行 Ubuntu 的笔记本电脑上尝试过此操作——两者的结果相同。

那么,在 Linux 下是否真的有办法从键盘发送 CR,为什么需要发送两次 EOF?

答案1

那么,在 Linux 下有没有办法从键盘发送 CR

发送 CR,但 tty 层会默认将其转换为 LF,因此程序无法收到CR。如果要避免这种情况,请使用tcsetattr()禁用该模式。(但不要忘记先保存旧设置,然后在退出时重置它们。)ICRNL

同时搜索生/熟/cbreak模式。

为什么EOF需要发送两次?

实际上,在操作系统级别上不存在 EOF 结果这样的事情 - 相反,每当 read() 系统调用返回 0 字节时,libc 函数就会将其报告为 EOF。

因此 Ctrl+D 实际上只是告诉操作系统立即完成 read() 调用(即不等待换行符),并且只有当它导致 read() 调用完全不返回任何数据时,它才会成为 EOF 指示符。只有在换行符后立即按下它时才会发生这种情况或者在先前按下 Ctrl+D 之后。

您也会在其他程序中看到这种情况。运行strace -e read catstrace -e read ./myprogram以更详细地查看它发生的情况。

相关内容