【问题标题】:Why fflush(stdin) does not remove buffer (stdin) [duplicate]为什么 fflush(stdin)不删除缓冲区(stdin)[重复]
【发布时间】:2014-01-15 18:10:28
【问题描述】:

我有这样的测试代码

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

int main() {
    char c, str[20];
    printf("Enter a character : ");
    scanf("%c", &c);
    printf("Enter a string : ");
    fflush(stdin);
    gets(str);
    printf("\n\n\nResult : %c\n%s\n", c, str);
    return 0;
}

我读过一些文章说这段代码可以工作,因为在扫描 c 字符后,缓冲区中仍然有 '\n' 字符。 fflush(stdin) 会清除缓冲区,所以gets() 函数可以正常工作

但实际上,当我在 Mac OS 环境中编译和运行这段代码时, fflush(stdin) 什么也没做。我输入了一个字符(例如,'k'),然后它打印出 k 字符和一个 '\n' 字符。它假设允许我输入一个字符,一个字符串,然后打印它们。有谁知道为什么? 谢谢!

【问题讨论】:

  • The fflush(stdin) will clear the buffer 是错误的。 fflush 仅用于输出流。
  • 在点击“发布您的问题”按钮之前,您是否查看了“可能已经有答案的问题”?
  • 通过处理系统的实现。

标签: c macos


【解决方案1】:

fflush(3) 被记录为处理 输出 流,而不是输入流。

标准没有指定输入流的行为。

特别是POSIX specification for fflush 没有提到输入流。 所以从 POSIX 的角度来看,它可能是一个undefined behavior

但是,在 Linux 上 fflush(stdin) 是可能的(但我不推荐它)因为

对于与 seekable 文件相关的输入流(例如,磁盘文件, 但不是管道或终端),fflush() 丢弃任何缓冲的数据 已从底层文件中获取,但尚未使用 由应用程序。

对于输入流,fflush() 丢弃任何 已从基础文件中获取的缓冲数据,但具有 未被应用程序使用。

(注意提到了一个可搜索的文件;通常你的stdin是一个不是真正磁盘文件的终端,lseek(2)会在终端上失败)

顺便说一句,gets(3) 已弃用,因为 危险(可能是 buffer overflow!)并且具有来自 C11 标准的 disappeared。至少使用fgets(3),最好使用getline(3)。或许可以考虑GNU readline 库(它提供了很好的编辑能力)。

【讨论】:

  • 手册页与您相矛盾:“对于输入流,fflush() 会丢弃已从底层文件获取但尚未被应用程序使用的任何缓冲数据。”
  • @Joni 在某些实现中定义,例如 Linux,但在标准 C 中没有。
  • 这就是我指出的原因,@YuHao:也许 Basile 应该将 OP 指向 OS X 手册页而不是 Linux 手册页,因为他们正在使用它。
  • @YuHao @ Basile Starynkevitch 但是为什么它仍然没有像手册页描述的那样丢弃缓冲区数据?你想看看我的问题吗?stackoverflow.com/q/55038401/5983841
【解决方案2】:

因为fflush(stdin)undefined behavior

fflush() 函数仅用于streams open for output,而不是输入。此方法似乎确实适用于某些 C 编译器,但完全不可移植!因此,它不应该被使用。

【讨论】:

猜你喜欢
  • 2012-12-27
  • 2012-07-21
  • 1970-01-01
  • 2015-08-20
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多