1. 程式人生 > 其它 >C++基礎知識:fflush(stdin)的誤區

C++基礎知識:fflush(stdin)的誤區

技術標籤:C++c++linux程式語言

fflush(stdin)是一個計算機專業術語,功能是清空輸入緩衝區,通常是為了確保不影響後面的資料讀取(例如在讀完一個字串後緊接著又要讀取一個字元,此時應該先執行fflush(stdin);。

  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) 是不正確的,至少是移植性不好的。

2. 清空輸入緩衝區的方法

雖然不可以用 fflush(stdin),但是我們可以自己寫程式碼來清空輸入緩衝區。只需要在 scanf 函式後面加上幾句簡單的程式碼就可以了。

  #include <stdio.h>

  int main( void )

  {

  int i, c;

  for ( ; ; )

  {

  fputs("Please input an integer: ", stdout);

  scanf("%d", &i);

  if ( feof(stdin) || ferror(stdin) )

  {

  break;

  }

  while ( (c=getchar()) !='\n' && c !=EOF ) ;

  printf("%d\n", i);

  }

  return 0;

  }

  #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::max() 返回輸入緩衝的大小。

// ignore 函式在此將把輸入流中的資料清空。

// 這兩個函式的具體用法請讀者自行查詢。

 cin.ignore( numeric_limits<streamsize>::max(), '\n' );

  cout << value << '\n';

  }

  return 0;

  }

fflush(stdin);語句的作用

#include

  #include

  void main()

  {float com=0.0,sale;int i;

  char grade;

  clrscr();

  printf("\n Enter sale:");

  scanf("%f",&sale);

  fflush(stdin);

  printf("\n Enter grade:");

  scanf("%c",&grade);

  if(sale>10000)

  if(grade=='A')

  com=sale*0.1 ;

  else

  com=sale*0.08 ;

  else

  com=sale*0.05;

  printf("\n Com=%f",com);

  }

免費領取C++資料包
在這裡插入圖片描述