为什么fflush(stdin)不会删除缓冲区(stdin)

时间:2013-12-28 09:01:44

标签: c macos

我有一个像这样的测试代码

#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'字符。它假设允许我输入一个字符,一个字符串,然后打印它们。谁知道为什么? 谢谢!

2 个答案:

答案 0 :(得分:8)

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

  

标准未指定输入流的行为。

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

然而,在Linux上fflush(stdin)是可能的(但我不建议这样做),因为

  

对于与可搜索文件相关联的输入流(例如,磁盘文件,     但不是管道或终端),fflush()会丢弃任何缓冲的数据     已从基础文件中获取,但尚未使用     通过申请。

     

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

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

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

答案 1 :(得分:4)

因为fflush(stdin)undefined behavior

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