【问题标题】:Difference between fflush(stdin) and flushstdin()fflush(stdin) 和 flushstdin() 的区别
【发布时间】:2015-08-20 21:45:37
【问题描述】:

使用fflush(stdin)有什么区别 和flushstdin()?我知道的唯一区别是我需要在使用 flushstdin() 之前写下那个 void 的东西,但我不知道为什么。

void flushstdin()
{
    int c;
    while((c = getchar()) != '\n' && c != EOF); 
}
int main () {
    float a, b, c;
    float s=0, ar1=0, ar2=0;
    printf("Inform value of side A");
    while(scanf("%f",&a) != 1 || a <= 0){ 
        printf("Invalid value.\n");
        flushstdin();
    }
}

int main(){
    float a,b,c,s=0;
    printf("Inform value of side A.");
    while(scanf("%f",&a) != 1 || a<=0){
        printf("Invalid value.\n");
        fflush(stdin);
    }
}

我是初学者!哪个代码最好?或者他们是平等的?

【问题讨论】:

  • 你说的我需要在使用flushstdin()之前写下那个空的东西是什么意思?
  • @RSahu this: void flushstdin() { int c; while((c = getchar()) != '\n' && c != EOF);
  • 请告诉你“写那些空洞的东西”的人。你还应该告诉她这个“空的东西”是一个 function 并且没有“写”它(在文件的上下文中“写东西”有一定的语义),但是 define (这里也是declare)和稍后的call。他真的应该把条款弄对,这样其他人才能真正理解你在说什么。

标签: c stdin fflush


【解决方案1】:

不同之处在于flushstdin 是用户定义的,标准C 中刷新stdin 的唯一方法。
fflush 是标准库函数。 fflush(stdin); 将调用未定义的行为。

c- faq: 12.26a

fflush 仅为输出流定义。由于它对“flush”的定义是完成缓冲字符的写入(而不是丢弃它们),因此丢弃未读输入对于fflush 在输入流上没有类似的含义。

c-faq: 12.26b

没有标准方法可以从 stdio 输入流中丢弃未读字符。 一些供应商确实实现了fflush,以便fflush(stdin) 丢弃未读字符,尽管可移植程序不能依赖于此。 (stdio 库的某些版本实现了 fpurgefabort 调用,它们做同样的事情,但这些也不是标准的。)还要注意,刷新 stdio 输入缓冲区不一定足够:未读字符也可以累积在其他操作系统级别的输入缓冲区中。如果您尝试主动放弃输入(可能是因为预期会发出意外提示以确认破坏性操作,而意外键入的“y”可能是灾难性的),您将不得不使用特定于系统的技术来检测预输入输入的存在;见问题 19.1 和 19.2。请记住,如果您丢弃碰巧输入得太快的输入,用户可能会感到沮丧。

【讨论】:

  • 所以我不应该使用 fflush(stdin)??
  • @RafaelMoura 它不再是一个可移植的程序。
  • @BLUEPIXY 你是什么意思? =(
  • @RafaelMoura 无法保证在其他环境中的行为相同。
  • 即使在 fflush(stdin) 工作的地方,它“刷新”stdin 的意义与 OP 的 flushstdin 函数不同。看我的回答。
【解决方案2】:

它们完全不同。它们都可以“刷新”输入,但该词的含义不同。

fflush 是一个标准的 C 函数。它在stdin 等输入流上的行为是undefined——这意味着C 标准没有定义它的行为。

某些系统确实在输入流上定义了fflush 的行为。例如在 Linux 上:

对于输入流,fflush() 丢弃任何已缓冲的数据 从底层文件中获取,但尚未被 应用。

您可以依靠fflush(stdin) 来按照此描述运行如果您的程序在基于 Linux 的系统上运行,或者在记录相同行为的另一个系统上运行。您的程序的行为将不可移植;在其他系统上,它可能会以任意糟糕的方式运行。 (很可能如果 fflush(stdin) 不起作用,它只会返回错误指示,但不能保证。)

您自己的flushstdin 函数与fflush(stdin) 的Linux 行为不同。它读取并丢弃所有输入函数,直到第一个换行符或直到EOF(由文件结尾或错误触发)。无论输入是否被缓冲,它都会这样做。

例如,假设您键入字符hello(没有换行符),然后您的程序调用fflush(stdin)然后您输入了换行符。

fflush(stdin),鉴于 Linux 记录的行为,将丢弃 hello 并立即返回,将换行符留给以后的调用读取。它“刷新”stdin,因为它丢弃所有待处理的输入,无论它是什么。

您的flushstdin() 函数将读取并丢弃hello,然后等到您键入Enter(或Ctrl-D),然后读取并丢弃它.它读取并丢弃直到换行符或 EOF 的所有输入,无论它在调用时是否处于挂起状态。

同样,fflush(stdin) 的行为不是由 C 标准定义的,因此使用它会使您的程序不可移植(并且您的编译器不一定会警告您)。

顺便说一句,“那个空洞的东西”是flushstdin 函数的定义fflush 不需要它,因为这是已经为您定义的标准 C 库函数。

【讨论】:

  • 一个类型的字符怎么可能没有换行符?
  • @hacks:这取决于终端是处于熟模式还是原始模式,以及 stdin 是否是行缓冲...
  • @hacks:输入一些字符而不是换行符。
  • @KeithThompson;哈哈。当然可以,但是程序如何在不按 Enter 键的情况下调用 fflush(stdin)
  • @hacks:或许不是。实验表明,在 Linux 上 fflush(stdin) 不会刷新行缓冲字符。事实上,我根本看不到fflush(stdin) 有任何影响;也许我做错了什么。我没有计划在实际代码中使用它,所以也许我不会担心它。
【解决方案3】:

两个版本都有问题。

正如已经广泛记录的那样,fflush(stdin) 根据 C 标准具有未定义的行为。使用flushstdin() 函数的替代方案也好不了多少。我建议一次读取一行标准输入并使用sscanf() 解析它,所有这些都在一个实用函数中,您可以根据需要使用:

int readfloat(const char *prompt, float *val) {
    char buf[128];
    for (;;) {
        if (prompt) 
            fputs(prompt, stdout);
        if (!fgets(buf, sizeof(buf), stdin)) {
            printf("Premature end of file\n");
            return 1;
        }
        if (sscanf(buf, "%f", val) == 1 && *val > 0)
            return 0;
        printf("Invalid value.\n");
    }
}

int main(void) {
    float a, b, c, s = 0;
    if (readfloat("Enter value of side A: ", &a))
        return 1;
    ...
}

【讨论】:

    猜你喜欢
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 2011-05-15
    • 2012-07-21
    • 2016-09-28
    • 1970-01-01
    • 2012-02-25
    相关资源
    最近更新 更多