1.為什麼 fflush(stdin)是錯的
首先請看以下程式:
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”。這是因為 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) 也沒什麼大問題。以下是 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)是不正確的 ,至少是移植性不好的。