源自
c++primer 4th, 248頁
代碼
#include <iostream> #include <limits> #include <stdexcept> using namespace std; int main() { int ival; while(cin >> ival, !cin.eof()) { cout << "hello:" << cin.fail() << endl; if(cin.bad()) throw runtime_error("IO stream is corrupted!"); if(cin.fail()) { cerr << "bad data, try again." << endl; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); continue; } } }
幾個地方
1. 逗號表達式
首先計算每一個操作數,然后返回最右邊的操作數最為整個操作的結果,因此while(cin >> ival, !cin.eof())看重的只是!cin.eof(),而對前邊的cin>>val不關心。
2. 條件狀態
流狀態由eof, bad, fail, good指示,如果eof, bad, fail任何一個為true那么流監測狀態為錯誤狀態;相反都為false,則good為true.
其中badbit標志着系統級的故障,是不可回復的,如果流出現這種情況,流通常就不能繼續使用了;failbit標志着是可恢復的,可以修正。eofbit在遇到文件結束符時設置,此時還設置了failbit.
clear()和setstate()用於改變條件成員的狀態。clear()將條件重設為有效狀態(eof, bad, fail置為false;good置為true),setstate()把某個特定的流設為有效狀態。
3. cin
程序的輸入都建有一個緩沖區,即輸入緩沖區。一次輸入過程是這樣的,當一次鍵盤輸入結束時會將輸入的數據存入輸入緩沖區,而cin函數直接從輸入緩沖區中取數據。正因為cin函數是直接從緩沖區取數據的,所以有時候當緩沖區中有殘留數據時,cin函數會直接取得這些殘留數據而不會請求鍵盤輸入.
注意
處理間隔符號(嚴格講是重定向符號>>, <<):遇到Enter、Space、Tab鍵,會自動當作間隔符號(當然,會把他們讀入到輸入緩沖區,但是處理的時候會丟棄掉)。
cin >> val 的返回值是cin, 即左值(同樣cout<<val返回左值cout),這樣就可以把cin >> val1; cin >> val2 合並為cin>>val1>>val2;
4. ignore函數
作用:提取輸入字符並丟棄他們。
函數原型:istream& ignore (streamsize n = 1, int delim = EOF)
讀取到前n個字符或在讀這n個字符進程中遇到delim字符就停止,把讀取的這些東西丟掉。
案例:
#include <iostream> #include <fstream> #include <sstream> #include <limits> #include <stdexcept> #include <typeinfo> using namespace std; int main() { int val1, val2; while(1) { cin >> val1; cin.ignore(5, '9'); cin >> val2; cout << "val1:" << val1 << endl; cout << "val2:" << val2 << endl; } }
運行結果

注意:如果讀了n個字符,后面這個正好是停止字符,那么都讀出來干掉(例子的最后一個)!
numeric_limits<streamsize>::max() 此時讀取的為最大長度,已經沒有界限,只能靠停止符終止。本例中為‘\n’,即從回車后開始讀取
5. 為何必須有ignore()函數
cin.clear()把failbit位清零,但是錯誤的輸入(不是指回車)還是在緩沖區,每次一讀錯誤就做相同的處理,如果沒有ignore(),那么當輸入錯誤時,就會無限循環。並且還不是簡單的cin.ignore(),默認的為ignore(1, '\n'),這樣會導致輸入幾個錯誤的字符循環幾次,例如
while(cin >> val, 1) { cout << "hello " << endl; cin.clear(); cin.ignore(); }

