【问题标题】:End while loop when 'Enter''Enter' 时结束 while 循环
【发布时间】:2014-04-20 16:03:19
【问题描述】:

我正在尝试创建一个循环,该循环将在没有用户输入的情况下无限运行,直到按下“Enter”。 这是我的程序的简化版本:

do {

printf("Hello\n");

}while(!getchar());

当我编译和运行程序时只输出一个'Hello'并且程序不会继续,直到按下Enter然后程序将退出。我可以知道我错了哪一部分吗?

谢谢。

【问题讨论】:

  • 在哪个操作系统上?
  • 我正在尝试创建一个循环,该循环将在没有用户输入的情况下无限运行,直到按下“Enter”。 - 当我编译并运行程序时,只输出一个“Hello”并卡住,直到按下 Enter。 - 看起来你得到了你需要的东西
  • 按“Enter”也是一种用户输入......:P
  • 亲爱的男孩,它被称为缓冲。 stackoverflow.com/questions/4327942/non-buffering-stdin-reading
  • 您好,感谢您的回复。我想要的是程序重复打印“Hello”,直到我按下回车键。但是程序现在所做的只是输出一个“Hello”并卡住,直到我按 Enter 退出它。我可以知道我错了程序不会重复打印的部分吗? @BasileStarynkevitch:Linux

标签: c while-loop do-while getchar


【解决方案1】:

这并不容易。您的问题是标准 I/O 函数是同步的。您的getchar 正在等待一些输入(准确地说是一行输入),它会阻止程序的执行,直到按下Enter。要继续执行而不阻塞,您需要使用异步 I/O 操作或select(或poll)。 Select 允许您检测下一个 I/O 操作是否会阻塞。查看select 的文档并尝试以下操作:

#include<stdio.h>
#include<unistd.h>
#include <sys/select.h>

int main() {
    fd_set          s;
    struct timeval  timeout;

    timeout.tv_sec = 0;
    timeout.tv_usec = 100000;

    do {
        printf("Hello\n"); 
        fflush(stdout);
        FD_ZERO(&s);
        FD_SET(STDIN_FILENO, &s);
        select(STDIN_FILENO+1, &s, NULL, NULL, &timeout);
    } while (FD_ISSET(STDIN_FILENO, &s) == 0);

}

【讨论】:

  • 这可能不会按预期工作,因为内核正在缓冲 tty 输入行。
  • select 是老式的,请改用poll(2)
  • @BasileStarynkevitch 该程序正在运行,并且在我的 Linux 机器上运行。 poll 和 select 之间的选择是一个品味问题。
  • 感谢您对异步 IO 和阻塞的额外解释。我之前怀疑是否可以在顺序程序中完成,我想制作另一个线程来停止当前的线程。仍在学习,但谢谢。
  • @user3326504 如果您只想中断程序,标准方法是捕获 SIGINT 和 SIGTERM 信号(即来自终端的 Control-C)并对这些信号执行您自己的操作。请参阅函数 signal 的手册页来设置您自己的信号处理。
【解决方案2】:

您的程序卡住了,因为 getchar() 函数正在等待输入。当你输入一些东西(回车)时,getchar() 返回非零值,所以 while 语句出错,这就是循环结束的原因。

【讨论】:

    【解决方案3】:

    在 Linux 上,终端是一个 tty,它通常以某种方式被内核缓冲。阅读tty demystified 和关于line discipline

    您可以使用ncursesreadline

    阅读getchar(3) 手册页(例如,在终端中使用man 3 getchar)。它说

    getchar() 将读取的字符返回为 unsigned char 在文件结尾或错误时强制转换为 int 或 EOF。

    所以你的测试是错误的,你可能想要while(getchar() != EOF),它不等待一些键盘输入。换句话说,getchar 总是阻止用户输入。您可以使用 Ctrl D

    给出文件结尾

    【讨论】:

      【解决方案4】:

      需要弄清楚规范与非规范终端输入的区别

      正如你所尝试的那样,我在canonical 终端上想,那么你现在已经有什么限制了。所以我只是向你解释一下non-canonical 终端

      对于非规范输入——想想vivim 或其他任何东西——你按下一个字符,它立即可供程序使用。直到您返回时,您才会被阻止。系统不对字符进行编辑;输入后,它们就可供程序使用。由程序来适当地解释事物。现在,vim 确实做了一些看起来有点像规范输入的事情。例如,退格键向后移动,在输入模式下会擦除那里的内容。但那是因为 vim 选择让它表现得像那样。

      所以你需要使用non-canonical flavor

      【讨论】:

      • 我认为“非规范”称为“原始输入模式”
      • @BasileStarynkevitch 我认为是这样,但更多信息请查看gnu.org/software/libc/manual/html_node/…
      • 您好,感谢您的回复。我在 linux 终端上编译这个,但我想同样的问题也会出现在其他操作系统上?我以前读过规范和非规范,但我不知道如何在这种情况下应用它。谢谢。
      猜你喜欢
      • 2023-03-15
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      • 2014-10-31
      • 2019-03-15
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多