【问题标题】:Unix(Mac OS) terminal does not honor Ctrl+D as EOF [closed]Unix(Mac OS)终端不将 Ctrl+D 视为 EOF [关闭]
【发布时间】:2020-02-20 22:34:59
【问题描述】:

我遇到的问题: 当我在玩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
     * https://stackoverflow.com/a/1799024/5450745
     * */
    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,它只会将终端从一个窗口拆分为两个。

我该怎么做才能让EOF 再次启用?

谢谢!

【问题讨论】:

  • 投票迁移到superuser.com 因为这不是编程问题,而是终端配置问题。
  • 原始模式输入不支持任何特殊字符——没有 EOF、没有擦除、没有中断、没有退出、没有杀死等。也许 stty cbreak——我没有尝试过,而且我我不确定。请注意,您目前也无法删除字符。 (而一键stty 标志是icanon/-icanon。)
  • 您的问题与 MacOS 无关,与您的 stty 通话有关。如果您想按照作者的意图进行练习,请摆脱 stty 调用。如果你想在输入字符时立即看到字符——就像我记得 所做的那样,我第一次在 K&R 中进行了类似的练习——那么是的,你将不得不修补使用 tty 模式,但您还必须自己检查 control-D。最简单的方法是将循环更改为while ((ch=getchar()) != EOF &amp;&amp; ch != 4)
  • 您实际上是在按ctrl+d 而不是command+d?因为command+d是MacOS终端中分割窗口的默认快捷方式。
  • 您可以使用while ((ch=getchar())!= EOF &amp;&amp; ch != '\004'){,但如果stty 命令有效,则不会检测到EOF,您可以将其简化为while ((ch=getchar()) != \004'){. The value '\004'` (相当于'\4''\x04'4)也是control-D 的符号。

标签: c macos terminal getchar stty


【解决方案1】:

此代码适用于我运行 macOS Catalina 10.15 的 Mac。我希望它在几乎任何你可以使用的类 Unix 系统上都能正常工作,包括旧版本的 macOS。它通过比较 ch'\004'(八进制 4 — 标准 C 中的许多其他可写方式,包括 4)来发现 control-D,并在键入时检测并终止循环。 p>

#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
     * https://stackoverflow.com/a/1799024/5450745
     * */
    system("/bin/stty raw");

    while ((ch = getchar()) != EOF && ch != '\004')
    {
        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 == '\004' 的测试确实会检测到何时键入 control-D。 (空格消除代码也可以。)

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

【讨论】:

  • 有效!谢谢!
猜你喜欢
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 2015-10-23
  • 1970-01-01
  • 2010-09-30
  • 2017-05-04
  • 2013-03-18
  • 1970-01-01
相关资源
最近更新 更多