在別人的程序裏看到這個函數,本着學習的態度整理一番。linux
p.s. 新添加一些內容沒,我從 關於fflush(stdin)清空輸入緩存流(C/C++) 新手必看!!這裏看來的,對理解緩衝區有很大幫助。ios
在printf()後使用fflush(stdout)的做用是馬上將要輸出的內容輸出。
當使用printf()函數後,系統將內容存入輸出緩衝區,等到時間片輪轉到系統的輸出程序時,將其輸出。
使用fflush(out)後,馬上清空輸出緩衝區,並把緩衝區內容輸出。
例如:c++
for (ctr = 1; ctr <= wait; ctr++) { printf("."); /* print a dot */ fflush(stdout); /* force dot to print on buffered machines */ sleep((int) 1); /* pause 1 second */ }
用fflush(stdout)能使機器每輸出一個.暫停一秒鐘,而不會出現亂序(例如:PP。。。PP。PPP。。。等)現象。緩存
一個經典的例子:函數
#include <stdio.h> int main() { char c; scanf("%c", &c); printf("%d\n", c); //fflush(stdin); // 沖掉「馬桶」中的無用值 scanf("%c", &c); printf("%d\n", c); return 0; }
若是輸入1後回車,輸出的是49和10,很正常,由於回車就是在ASCii中就是49。學習
功能:清空輸入緩衝區,一般是爲了確保不影響後面的數據讀取(例如在讀完一個字符串後緊接着又要讀取一個字符,此時應該先執行fflush(stdin);)。.net
這裏給你們提個醒,爲何用fflush(stdin)是錯的?code
先看下下面的程序blog
#include <stdio.h> int main( void ) { int i; for (;;) { fputs("Please input an integer: ", stdout); scanf("%d", &i); printf("%d\n", i); } return 0; }
這個程序首先會提示用戶輸入一個整數,而後等待用戶輸入,若是用戶輸入的是整數,程序會輸出剛纔輸入的整數,而且再次提示用戶輸入一個整數,而後等待用戶 輸入。可是一旦用戶輸入的不是整數(如小數或者字母),假設 scanf 函數最後一次獲得的整數是 2 ,那麼程序會不停地輸出「Please input an integer: 2」。ci
這是由於 scanf("%d", &i); 只能接受整數,若是用戶輸入了字母,則這個字母會遺留在「輸入緩衝區」中。由於緩衝中有數據,故而 scanf 函數不會等待用戶輸入,直接就去緩衝中讀取,但是緩衝中的倒是字母,這個字母再次被遺留在緩衝中,如此反覆,從而致使不停地輸出「Please input an integer: 2」。(這裏你們應該能一會兒醒悟,原來有個緩衝區,爲何之前學習的時候老師一直沒有重點提過,這個緩衝區的機制多麼重要啊,之前寫程序踩了多少坑就是由於這個!!)
也許有人會說:「竟然這樣,那麼在 scanf 函數後面加上‘fflush(stdin);’,把輸入緩衝清空掉不就好了?」然而這是錯的!C和C++的標準裏歷來沒有定義過 fflush(stdin)。也許有人會說:「但是我用 fflush(stdin) 解決了這個問題,你怎麼能說是錯的呢?」的確,某些編譯器(如VC6)支持用 fflush(stdin) 來清空輸入緩衝,可是並不是全部編譯器都要支持這個功能(linux 下的 gcc 就不支持),由於標準中根本沒有定義 fflush(stdin)。MSDN 文檔裏 也清楚地寫着fflush on input stream is an extension to the C standard(fflush 操做輸入流是對 C 標準的擴充)。
固然,若是你絕不在意程序的移植性,用 fflush(stdin) 也沒什麼大問題。
那麼爲了移植性以及程序的魯棒性,咱們應該怎麼作?
清空輸入緩衝區的方法
/* C 版本 */ #include <stdio.h> int main( void ) { int i, c; for ( ; ; ) { fputs("Please input an integer: ", stdout); scanf("%d", &i); if ( feof(stdin) || ferror(stdin) ) { /* 若是用戶輸入文件結束標誌(或文件已被讀完), */ /* 或者發生讀寫錯誤,則退出循環 */ /* do something */ break; } /* 沒有發生錯誤,清空輸入流。 */ /* 經過 while 循環把輸入流中的餘留數據「吃」掉 */ while ( (c = getchar()) != '\n' && c != EOF ) ; /*可直接將這句代碼當成fflush(stdio)的替代,直接運行可清除輸入緩存流*/ /* 使用 scanf("%*[^\n]"); 也能夠清空輸入流, */ /* 不過會殘留 \n 字符。 */ printf("%d\n", i); } return 0; }
上面是c版本的,下面是c++版本的。
/* C++ 版本 */ #include <iostream> #include <limits> // 爲了使用numeric_limits using std::cout; using std::endl; using std::cin; using std::numeric_limits; using std::streamsize; int main() { int value; for ( ; ; ) { cout << "Enter an integer: "; cin >> value; if ( cin.eof() || cin.bad() ) { // 若是用戶輸入文件結束標誌(或文件已被讀完), // 或者發生讀寫錯誤,則退出循環 // do something break; } // 讀到非法字符後,輸入流將處於出錯狀態, // 爲了繼續獲取輸入,首先要調用 clear 函數 // 來清除輸入流的錯誤標記,而後才能調用 // ignore 函數來清除輸入流中的數據。 cin.clear(); // numeric_limits<streamsize>::max() 返回輸入緩衝的大小。 // ignore 函數在此將把輸入流中的數據清空。 // 這兩個函數的具體用法請讀者自行查詢。 cin.ignore( numeric_limits<streamsize>::max(), '\n' ); cout << value << '\n'; } return 0; }
我的以爲這兩個版本寫的不錯,能夠添加到本身的私有庫裏。根據這個原理本身還能夠改寫一些別的版本。
c99對這個函數的定義:
int fflush(FILE*stream); 若是stream指向輸出流或者更新流(update stream),而且這個更新流 最近執行的操做不是輸入,那麼fflush函數將把任何未被寫入的數據寫入stream 指向的文件(如標準輸出文件stdout)。不然,fflush函數的行爲是不肯定的。 fflush(NULL)清空全部輸出流和上面提到的更新流。若是發生寫錯誤,fflush 函數會給那些流打上錯誤標記,而且返回EOF,不然返回0。
這個函數仍是頗有用的,能夠加深對緩存的理解。沒有想到一個輸入都有這麼多須要關注的東西,真的是c++是學一生的東西!-_-