天天看點

C++中輸入流istream狀态管理11 輸入流與cin2 錯誤處理3 程式設計實踐

流(stream)是一個傳送和格式化固定寬度字元的對象。包括輸入流、輸出流和同時實作兩種功能的輸入/輸出流。其中,用istream及其派生類表示輸入流,用ostream及其子類表示輸出流,用iostream及其子類表示輸入輸出流。

1 輸入流與cin

cin是輸入流istream類的對象,它是一個全局變量。cin通過提取符(extractor)“>>”從流中擷取資訊。

2 錯誤處理

2.1 流狀态位

ios_base類中聲明了所有流類共有的内容,不依賴于流所處理的字元類型。其中,定義了4個标志位來測試流的狀态,badbit、eofbit、failbit和goodbit。其中,badbit位表示了在流緩沖區中發生了緻命性錯誤,流将不能繼續使用;eofbit位表示輸入結束,例如按下了Ctrl-Z;failbit位表示I/O操作由于非法資料而失敗,流可以繼續使用;goodbit位表示一切正常,沒有錯誤發生,也沒有發生輸入結束。

2.2 流狀态函數

通過good()、eof()、fail()和bad()等成員函數擷取流狀态。這些函數的傳回值是boolean類型,分别對應goodbit、eofbit、failbit和badbit标志位的。可以通過調用以上的成員函數,根據其傳回的布爾值來測試發生了什麼情況,傳回的布爾值表示相應的流狀态。

當除goodbit之外的其它3個标志位沒有被設定時,流類的成員函數good()傳回真。如果eofbit被設定則函數eof()傳回真,表明程式試圖從已經到達末尾的流(通常是檔案流)中讀取資料。如果設定了failbit和badbit标志位中的任意一個,則函數fail()傳回真,隻有設定了badbit标志位,函數bad()才傳回真。

2.3 清空标志位

一旦設定了流狀态中的任何一個标志位,這些标志位将保持不變。可以通過調用clear()函數來清空标志位。如:

cin.clear();
           

2.4 程式設計驗證

在控制台程式中,有如下代碼

int i;
cin >> i;
bool good = cin.good();
bool bad = cin.bad();
bool fail = cin.fail();
bool eof = cin.eof();
           

程式運作後,在控制台中輸入整數5,此時good的值是true,而其它三個值是false。輸入Ctrl-Z,此時good和bad的值是false,fail和eof的值是true。如果輸入一個字元,如’a’,此時good、bad和eof的值是false,而fail的值是true。

3 程式設計實踐

在CSDN論壇上有朋友問到這樣一個問題:

int i;
while(1)
{
   cin >> i;
   cout << i << endl;
}
           

運作以上代碼時,輸入正确格式(整數)時,程式可以正确運作。當輸入不正确的格式時,如輸入字元’a’,此時程式不報錯,但是會一直輸出i的最後一次正确值。也就是說,當輸入錯誤格式時

cin >> i;
           

此代碼不起作用了。

3.1 問題分析

從“2錯誤處理”中分析可知,當輸入不正确格式的數時,cin的failbit位将會被設定,導緻cin的提取符失效。

3.2 問題解決

使用“2.3 清空标志位”中提到的clear()函數,清空failbit位。之後調用ignore()函數跳過流中格式不正确的資料。

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

其中,ignore()函數的第一個參數表示要跳過的字元的數目,第二個參數指定了遇到哪個字元時,ignore()函數退出。

numeric_limits是一個模闆類,該類用于描述内置數字類型的數學屬性,streamsize是流大小的機關,max()函數是numeric_limits類的成員函數,該函數的作用是傳回指定類型(streamsize類型)的最大值。第二行代碼的含義是,當輸入流中的資料出現錯誤時,跳過該流,此時流的狀态為good()。

3.3 修改後的代碼

修改後的代碼如下所示

int i;
while (1)
{
cout << "請輸入一個整數:" << endl;
cin >> i;
while(cin.fail())
{
cout << "輸入格式錯誤,請重新輸入!" << endl;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "請輸入一個整數:" << endl;
cin >> i;
}
cout << i << endl;
}
           

此時,當輸入不正确格式的資料時,程式會顯示錯誤提示資訊,并且可以重新輸入。

繼續閱讀