【c++】流狀態的查詢和控制


源自

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();
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM