Unix(Mac OS) 终端不支持 Ctrl+D 作为 EOF

Unix(Mac OS) terminal does not honor Ctrl+D as EOF

我遇到的问题: 当我玩 getchar() 行为时,我发现我的终端(macOS Mohave 版本 10.14.6 18G87)不支持 Ctrl+D 作为 EOF。

我是怎么遇到这个问题的:

getchar()的代码附在下面,如果输入的字符不为空,基本上这段代码就是echo getchar(),否则,对于多个连续的空白字符,它只输出一个空白字符。 代码本身有效,但是当 运行 它在终端中时,终端不会将 Ctrl+D 视为 EOF,因此 代码永远不会终止。 我确定这是因为我错误地使用了 system ("/bin/stty raw");system ("/bin/stty cooked"); ,但是,我不知道如何解决它。

 /* K&R C Exercise 1-9. Write a program to copy its input to its output,
 * replacing each string of one or more blanks by a single blank.*/

#include <stdio.h>
#include <stdlib.h>

int main(void){

    int ch;
    int prev = -1;

    /* if you are in a UNIX like environment
     * the ICANON flag is enabled by default, so input is buffered until the next '\n' or EOF
     * 
     * */
    system ("/bin/stty raw");

    while ((ch=getchar())!= EOF){
       if (ch != ' ' ){
           if (prev == ' '){
               putchar(prev);
               putchar(ch);
           }
           else{
               putchar(ch);
           }
           prev = ch;
       }
       else{

           prev = ch;
           continue;
       }

    }
    /* use system call to set terminal behaviour to more normal behaviour */
    system ("/bin/stty cooked");

    return 0;
}

我检查了 stty,但是,它确实将 EOF 配置为 Ctrl +D。但是,现在,如果我按 Ctrl + D,它只会将终端从一个 window 拆分为两个。

如何才能允许 EOF 重新启用?

谢谢!

此代码适用于我的 Mac 运行 macOS Catalina 10.15。我希望它在几乎任何你可以接触到的类 Unix 系统上都能以基本相同的方式工作,包括旧版本的 macOS。它通过比较 ch'[=12=]4' 来发现 control-D(八进制 4 — 在标准 C 中可写许多其他方式,包括仅 4)键入并终止循环时。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int ch;
    int prev = -1;

    /* if you are in a UNIX like environment
     * the ICANON flag is enabled by default, so input is buffered until the next '\n' or EOF
     * 
     * */
    system("/bin/stty raw");

    while ((ch = getchar()) != EOF && ch != '[=10=]4')
    {
        if (ch != ' ')
        {
            if (prev == ' ')
            {
                putchar(prev);
                putchar(ch);
            }
            else
            {
                putchar(ch);
            }
            prev = ch;
        }
        else
        {
            prev = ch;
            continue;
        }
    }
    /* use system call to set terminal behaviour to more normal behaviour */
    system("/bin/stty cooked");

    return 0;
}

当然,输出显示有点奇怪——例如,键入 return 不会将光标移动到下一行。但是 ch == '[=14=]4' 的测试确实检测到何时键入 control-D。 (space 消除代码也有效。)

使用 stty cbreak 而不是 stty raw 使中断启用,但通过 control-D 的 EOF 仍然被禁用。