fflush(stdin)和flushstdin()之间的区别

时间:2015-06-05 20:13:25

标签: c stdin fflush

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

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);
    }
}

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

3 个答案:

答案 0 :(得分:8)

区别在于flushstdin是用户定义的,是标准C中唯一可以刷新stdin的方式。
fflush是标准库函数。 fflush(stdin);将调用未定义的行为。

c- faq: 12.26a

  

fflush仅针对输出流进行定义。由于它定义了&#34; flush&#34;是完成缓冲字符的写入(不丢弃它们),丢弃未读输入对输入流上的fflush不是类似的意思。

c-faq: 12.26b

  

没有标准方法可以从stdio输入流中丢弃未读字符。 有些供应商会实施fflush,以便fflush(stdin)丢弃未读的字符,但便携式程序不能依赖于此。 (某些版本的stdio库实现了fpurgefabort调用,它们执行相同的操作,但这些调用也不是标准的。)另请注意,刷新{{ 1}}输入缓冲区不一定足够:未读字符也可以在其他OS级输入缓冲区中累积。如果您试图主动放弃输入(可能是因为预期会发出意外提示来确认破坏性行为,而意外打字并且可能会造成灾难性后果),您可能会必须使用特定于系统的技术来检测预先输入类型的输入;见问题19.1和19.2。请记住,如果丢弃输入错误的输入,用户可能会感到沮丧。

答案 1 :(得分:2)

他们完全不同。他们都可以&#34;冲洗&#34;输入,但在不同的意义上。

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

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

  

对于输入流,fflush()会丢弃已经存在的所有缓冲数据   从底层文件中获取,但尚未被使用   应用

如果您的程序在基于Linux的系统上运行,或者在另一个记录相同行为的系统上运行,则可以依赖fflush(stdin)按照此说明行事。您的程序行为将无法移植;在其他系统上,它可能会以任意不好的方式运行。 (如果fflush(stdin)不起作用,很可能除了返回错误指示之外什么都不做,但这不能保证。)

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

例如,假设您输入字符hello(没有换行符),然后您的程序调用{​​{1}},然后您输入换行符。

fflush(stdin),鉴于Linux记录的行为,将丢弃fflush(stdin)并立即返回,让新行在稍后的调用中被读取。它&#34;冲洗&#34; hello在某种意义上它会丢弃所有待处理的输入,无论它是什么。

您的stdin函数将读取并放弃flushstdin(),然后等到键入 Enter (或 Ctrl-D ),然后阅读并丢弃。它会读取并丢弃所有输入到换行符或EOF,无论它是否在通话时等待。

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

顺便说一下,&#34;那无效的东西&#34;是fflush(stdin)函数的定义flushstdin不需要它,因为它是已经为您定义的标准C库函数。

答案 2 :(得分:1)

两个版本都有问题。

正如已经广泛记载的那样,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;
    ...
}