4

我有这个代码

while(1){
    printf("hello world !\n");
    fgetc(stdin);
}

当它运行时,我输入这样的字母:

hello world !
a

它在下一个循环中忽略 fgetc(stdin) 并打印 hello world 两次而不等待输入。

hello world !
a
hello world !
hello world !
a
hello world !
hello world !
a
hello world !
hello world !
a
hello world !
hello world !

我曾尝试将 fflush(stdin) 放在 fgetc(stdin) 之前或之后,但它仍然会产生相同的行为,我做错了什么?

4

4 回答 4

8

那是因为您实际上输入了两个字符:“a”和换行符。此外,由于终端通常是行缓冲的,因此您的程序只有在您点击换行时才会看到您的输入。输入更长的文本行也会提供信息。

如果你想改变这种行为,你有两个选择:读取整行(即所有字符到换行符或文件结尾)或将终端切换到非规范模式。如果您正在使用文本编辑器等交互式终端应用程序,则后者是有意义的。有关详细信息,请参见termios 手册页。简而言之,您需要将 MIN 和 TIME 选项设置为零,以便在数据可用时立即从终端返回读取。如果您确实走这条路,请确保在退出时切换终端,包括由于接收到信号。

fflush()影响输出,而不是输入。

于 2012-08-21T22:21:00.657 回答
5

终端往往是行缓冲的,这意味着可以逐行访问流内容。

因此,当fgetc开始从 STDIN 读取时,它正在读取整行,其中包括结束该行的换行符。那是您正在阅读的第二个字符。

至于fflush,那是用于刷新输出缓冲区,而不是输入缓冲区。

因此,您在这里要做的是通过读取输入缓冲区直到其为空来清除输入缓冲区,或者只是显式忽略换行符。

于 2012-08-21T22:24:25.823 回答
2

有两个字符:a\n(换行符)。您的循环读取读取a,然后循环并打印“hello world!”。然后它会看到\n并循环并打印“hello world!”。当您在终端中键入a+\n时,它将两个字符存储在标准输入缓冲区中。fgetc(stdin);如果有可用的字符,将从标准输入缓冲区读取,否则它会等待直到将字符添加到缓冲区。

由于终端是行缓冲的(即,在到达换行符之前不要将内容发送到程序)您有几个选择:

  • 将整行读入缓冲区,但只取第一个字符
  • 忽略换行符
  • 关闭行缓冲

要关闭行缓冲,请查看http://c-faq.com/osdep/cbreak.htmlhttp://www.flipcode.com/archives/_kbhit_for_Linux.shtmlhttp://ubuntuforums.org/showthread。 php?t=225713(虽然我没有在这里测试任何代码)。

于 2012-08-21T22:21:17.190 回答
1

你有两个字符,'a''\n'。这就是问题所在,因为 fgetc 只会读取一个字符。这是文档

如果您只输入一个'\n'- 仅点击输入 - 您将获得预期的行为。

希望能帮助到你!

于 2012-08-21T22:23:49.590 回答