【问题标题】:fflush(stdin) ANSI C [duplicate]fflush(stdin) ANSI C [重复]
【发布时间】:2012-07-21 05:15:40
【问题描述】:

我是 ANSI C 的初学者,我有一个问题,这可能是个愚蠢的问题,我很抱歉。

#include<stdio.h>
    main()
    {
          int age;
          printf("Hello World!\n");
          printf("Please enter your age: ");
          scanf("%d", &age);
          printf("You entered %d\n", age);
          fflush(stdin);
          getchar();
    }

这是我学习scanf函数的第二个程序。 我的问题是: 我知道定义了 printfscanffflushstdingetcharstdio.h 但只有当我使用 fflush(stdin) 我必须把 #includestdio.h> >,但是当使用任何其他方法时,我可以删除该行#include。

【问题讨论】:

  • 您是否已经包含任何其他头文件?
  • 不,这是代码。我不明白两者之间有什么区别
  • 值得注意的是,fflush(stdin) 虽然适用于某些实现,但它仍然是未定义的行为。根据标准,fflush 仅适用于输出/更新流。
  • 请注意,在某些系统上(尤其是带有 Microsoft 库的 Windows),fflush(stdin) 是已定义的行为。在许多系统上,根据 C 和 POSIX 标准,这是未定义的行为。另请参阅Using fflush(stdin)

标签: c fflush


【解决方案1】:

当您调用该标头中声明的任何函数时,您必须拥有#include &lt;stdio.h&gt;

好吧,这不是相当正确的。在 1989/1990 版本的语言标准中,调用可以创建函数的隐式声明。如果这恰好与正确的声明相匹配,您就可以侥幸逃脱;。否则你的程序的行为是不确定的——这意味着你仍然可能侥幸逃脱,但编译器不需要警告你。由于printf 采用可变数量的参数,您必须有一个可见的声明以避免未定义的行为——获得可见声明的方法是#include &lt;stdio.h&gt;

(您也可以自己声明该函数,但这很容易出错,而且没有充分的理由这样做。)

在 C99 及更高版本中,没有隐式声明。

main() 应该是int main(void)

fflush(stdin) 具有未定义的行为。如果您想丢弃在scanf() 调用之后输入的字符,您可以读取并丢弃它们。

【讨论】:

  • 请注意,即使是 C89/90 也需要在使用之前声明 any 可变参数函数,例如 printf()。当然,您可以(仍然可以)在使用它之前写 extern int printf(const char *fmt, ...);,这将达到目标。但是,包含标题要明智得多。
  • @JonathanLeffler:但它没有强制执行该要求。正如我所说,在 C90 中没有可见声明的情况下调用 printf 具有未定义的行为——但它很可能“起作用”。
  • 是的,这是未定义的行为。我也许应该说我的意思是“C89/90 标准”而不是“C89/90 实现”,但是我正在处理的答案中的陈述已经具备了这种资格。这只是一个小脚注,不是主要问题。
【解决方案2】:

您可能需要该头文件,以便定义 stdin。如果你关闭了编译器警告,编译器不会让你知道未定义的函数。 (如果他们真的是 未定义,稍后您将收到链接器错误)。 stdinFILE * 类型的变量,而不是函数。

请勿拨打fflush(stdin)。它具有未定义的行为。如果您需要清除输入缓冲区,请使用另一种方法。执行此操作的标准方法是尝试读取数据直到下一行结束:

int flush_line(FILE *file)
{
    int ch;
    do {
        ch = fgetc(file);
    } while (ch != '\n' && ch != EOF);
    if (ch == EOF && ferror(file)) {
        return -1;
    }
    return 0;
}

然后你会打电话给flush_line(stdin)

如果不考虑可移植性(注意这不适用于 Windows),您可以暂时将文件描述符设为非阻塞并从中读取 all 输入:

int flush_in(FILE *file)
{
    int ch;
    int flags;
    int fd;

    fd = fileno(file);
    flags = fcntl(fd, F_GETFL, 0);
    if (flags < 0) {
        return -1;
    }
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
        return -1;
    }
    do {
        ch = fgetc(file);
    } while (ch != EOF);
    clearerr(file);
    if (fcntl(fd, F_SETFL, flags)) {
        return -1;
    }
    return 0;
}

然后你会打电话给flush_in(stdin)

【讨论】:

  • @JonathonReinhart 这不是一场战斗,fflush(stdin) 不仅不可移植,而且在任何非行缓冲输入上都无法正确运行。
  • 哈哈,我喜欢发布该评论如何使我在该答案上获得-2。真傻,呵呵。
  • 使那个-3。 fflush(stdin) 没有做你认为它做的事情,并且一个被接受的答案是那个错误并且作者没有修复应该有一个很高的负面分数来提醒读者它是错误的。
猜你喜欢
  • 2015-06-26
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2014-05-19
  • 2018-06-15
  • 2012-12-27
相关资源
最近更新 更多