C++中清空緩衝區的方法

問題描述:輸入數據時希望有個合法性檢驗的問題,如果輸入的數據不合法則程序提示重新輸入。最初代碼如下:

#include <iostream>
#include <vector>


using std::cin ;
using std::cout ;
using std::endl;
using std::vector ;


int main()
{
int num;
vector<int> ivec;
do
{
cout<<"please enter some numbers:"<<endl;
while(cin>>num)
ivec.push_back(num);
if(ivec.size()==0)
cout<<"Error!"<<endl;


}while(ivec.size()==0);


//其他語句
}

這樣寫如果第一次正確輸入,程序運行正確。但如果第一次沒有輸入有效字符(比如輸入ctrl+z,回車)或者第一個輸入爲非法字符,則程序陷入死循環,不停的輸出提示信息,但是不允許用戶再次輸入。

正確寫法:

#include <iostream>
#include <vector>


using std::cin ;
using std::cout ;
using std::endl;
using std::vector ;


int main()
{
int num;
vector<int> ivec;
do
{
cout<<"please enter some numbers:"<<endl;

while(cin>>num)
ivec.push_back(num);


//增加了兩行
cin.clear();
cin.sync();   //或者用cin.ignore();


if(ivec.size()==0)
cout<<"Error!"<<endl;


}while(ivec.size()==0);
}

增加上面兩行之後,可以實現預定功能,程序運行正常。

說明原因:

首先需要了解cin的用法。程序的輸入都有一個緩衝區,當一次鍵盤輸入結束時會將輸入的數據存入輸入緩衝區,而cin函數直接從輸入緩衝區中讀取數據。這種緩衝機制規定,只有收到回車鍵時,纔會將所有輸入的數據一次性提交到cin函數。回車標誌一次輸入的完成,如果數據不夠,則會等待用戶繼續輸入;如果數據有多餘,則將多餘的數據存儲在輸入流緩衝區中,供下次使用。舉個栗子:

while(cin>>num)

cout<<num<<endl;

這條語句,如果輸入一次1   2   3   4 ,執行結果是:

1

2

3

4

執行過程如下:

第一次運行cin>>num的時候,輸入緩衝區爲空,所以會顯示下劃線讓用戶輸入。用戶輸入1  2  3  4  ctrl+z,回車,這時候cin讀入第一個整數1,然後輸出1和換行。

下一次執行 cin>>num的時候,緩衝區不爲空,所以不再要求用戶輸入,直接讀取第二個整數2,然後輸出2和換行。以此類推,依次輸出3 ,4。

然後cin檢查到結束標誌ctrl+z,cin>>num返回false,循環退出。

需要特別注意的一點是:當緩衝區中有殘留數據時,cin函數會直接去讀取這些殘留數據而不會請求鍵盤輸入。而且,回車符也會被存入輸入緩衝區中。

有了這些知識,就可以解釋原始代碼中的現象了。如果第一次沒有輸入有效字符,以ctrl+z加上回車鍵結束輸入後,回車符會被當成一個字符存入輸入緩衝區。下一次再運行時,到了while(cin>>num)這一步,由於緩衝區中已有一個回車符,所以cin函數直接去緩衝區中讀取回車符,而不允許用戶再次輸入數據,這就是第一次非法輸入後不能再次輸入數據的原因。由於需要的數據num是int型的,顯然讀取到的回車符仍然是非法的,程序再次進入下一個循環,並且一直這樣循環下去,這就是程序陷入死循環原因

解決辦法:

從上面的分析我們可以看出,導致問題的根本是輸入緩衝區沒有及時清空,以至於前一次的輸入影響了後面的輸入。因此,在輸入前加上清空輸入緩衝區的語句就可以解決問題。c++用於清空輸入緩存的函數有三個:cin.clear(),cin.sync(),cin.ignore()。


cin.clear()是用來更改cin的狀態標示符的,cin在接收到錯誤的輸入的時候,會設置狀態位good。如果good位不爲1,則cin不接受輸入,直接跳過。如果下次輸入前狀態位沒有改變那麼即使清除了緩衝區數據流也無法輸入。所以清除緩衝區之前必須要cin.clear()。


cin.ignore(a,ch):從輸入緩衝去中提取字符,提取的字符被忽略,不被使用。每拋棄一個字符,它都要計數和比較字符,如果計數值達到a或者被忽略的字符是ch,則cin.ignore()函數終止執行。默認參數是a=1,即僅忽略緩衝區中的第一個字符。它的一個常用功能是用來清除以回車結束的輸入緩衝區的內容,消除上一次輸入對下一次輸入的影響。比如cin.ignore(1024,'\n'),通常把第一個參數設置得足夠大,這樣實際上總是隻有第二個參數起作用,所以這一句就是把回車(包括回車)之前的所有字符從輸入緩衝區中清除。


cin.sync()的作用是清除輸入緩衝區全部的內容。


另外,函數fflush(stdin)的功能也是清空輸入緩衝區,但是此函數並不是在c/c++標準中定義的,它僅適用於部分編譯器(如VC),並非所有的編譯器都支持這個功能。經過實驗,在visual studio中用這個函數無法清空輸入緩衝區。

轉載自:https://blog.csdn.net/zhao708981169/article/details/36392681

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章