gcc下fflush(stdin)无效的解决

来源:互联网 发布:阿里云高可用 编辑:程序博客网 时间:2024/05/22 07:08
今天编译一程序涉及到了键盘缓冲区的清除问题,在VC下完全没问题的代码却不能在gcc下运行成功,作此笔记以留念: 
VC下代码: 
#include<stdio.h> 
void main() 
{ 
        float a,b; 
        int tag=0; 
        char ch; 
        float result; 

        printf("Input two number:"); 
        scanf("%f%f",&a,&b); 
        fflush(stdin); 
        printf("Input arithmetic lable(+-*/):"); 
        scanf("%c",&ch); 

        switch (ch) 
        { 
                case '+':result=a+b;break; 
                case '-':result=a-b;break; 
                case '*':result=a*b;break; 
                case '/':if(!b) 
                         { 
                                 printf("divisor is zero!\n"); 
                                 tag=1; 
                         } 
                         else 
                                 result=a/b; 
                         break; 
                default:printf("illegal arithmetic lable\n"); 
                        tag=1; 
        } 
        if(!tag) 
                printf("%.2f %c %.2f=%.2f\n",a,ch,b,result); 
} 

一网友的解释如下:

如何清除stdin缓存中的数据?

一。这问题没有什么很标准的做法:
方法1、fflush(): VC上面使用fflush()可以成功, 而在gcc上面使用fflush()却不能成功。
方法2、setbuf(): 虽然在gcc上面,使用这种方式确实可以清空输入流. 但不建议使用。
方法3、通过 while 循环把输入流中的余留数据“吃”掉:
        int c;
        while ((c=getchar()) != '\n' && c != EOF);
(使用while(getchar()!='\n') 也可以 )
        /*可直接将这2句代码当成fflush(stdin)的替代,直接运行可清除输入缓存流*/

二。解释:

1. fflush()不行的原因如下:

C-FAQ中如下:
Question 12.26
How can I flush pending input so that a user's typeahead isn't read at the next prompt? Will fflush(stdin) work?

--------------------------------------------------------------------------------
fflush is defined only for output streams. Since its definition of ``flush'' is to complete the writing of buffered characters (not to discard them), discarding unread input would not be an analogous meaning for fflush on input streams.

There is no standard way to discard unread characters from a stdio input stream, nor would such a way be sufficient unread characters can also accumulate in other, OS-level input buffers.

C标准(ISO/IEC 9899:1999 standard)规定fflush(stdin)操作是未定义的<参看《ISO/IEC 9899:1999 standard》p270>;。也就是说不一定能实现刷新功能,但有的编译器可能不遵循标准,对fflush(stdin)操作不予警告,并且有时可能产生正确的结果,但最好不要这样使用。
VC上面使用fflush()可以成功, 而在gcc上面使用fflush()却不能成功。


以下是 C99 对 fflush 函数的定义:

int fflush(FILE *stream);
如果 stream 指向输出流或者更新流(update stream),
并且这个更新流最近执行的操作不是输入,
那么 fflush 函数将把这个流中任何待写数据传送至宿主环境(host environment)写入文件。
否则,它的行为是未定义的。

原文如下:
int fflush(FILE *stream);
If stream points to an output stream or an update stream in which
the most recent operation was not input, the fflush function causes
any unwritten data for that stream to be delivered to the host environment
to be written to the file; otherwise, the behavior is undefined.

其中,宿主环境可以理解为操作系统或内核等。

由此可知,如果 stream 指向输入流(如 stdin),那么 fflush 函数的行为是不确定的。故而使用 fflush(stdin)   是不正确的,至少是移植性不好的。

2. setbuf()的方法也是不符合标准的. 虽然在有些场合它通过将输入设置为无缓冲形式, 以此来刷新输入流, 但是不太可靠。
虽然在gcc上面,使用这种方式确实可以清空输入流. 但不建议使用. 
 

其编译后不能运行成功的主要原因在于gcc下fflush(stdin)没起作用,所以  
     printf("Input two number:"); 
        scanf("%f%f",&a,&b); 
        fflush(stdin); 
        printf("Input arithmetic lable(+-*/):"); 
        scanf("%c",&ch); 
可以改为: 
printf("Input two number:"); 
scanf("%f%f",&a,&b); 
printf("Input arithmetic lable(+-*/):"); 
scanf("  "); 
scanf("%c",&ch); 

这样在gcc下即可编译执行成功,不足之处望指正共同进步。。。。。 

转自: http://hi.baidu.com/agassi_p/blog/item/1e4801824e29a2b50df4d257.html

0 0
原创粉丝点击