gcc下fflush(stdin)失效

今天編譯一程序涉及到了鍵盤緩衝區的清除問題,在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);


        /*可直接將這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)寫入文件。

否則,它的行爲是未定義的。對於fflush(FILE *out)這種是肯定會成功的,但是對於fflush(stdin),fflush(stdout),不能保證一定能刷新。


原文如下:
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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章