C++ Primer 4th中第八章的一個錯誤 — 遺漏了cin.ignore

來源:互聯網
上載者:User
第八章有個例子,非常簡單,就是讀入使用者輸入,賦給一個int,這裡面有一個判斷,就是如果使用者輸入的不是int,那麼,cin就會變成invalid,裡面就有condition state,於是我們可以catch這個state並clear,然後繼續讀入。

但是書上給的例子有個錯誤,原來的程式是這樣的:

Code: Select all
#include <iostream>
#include <stdexcept>
using namespace std;

int main(int argc, char **argv)
{
    int ival;
    // cout << "Begin state is: " << cin.rdstate() << endl;
    while (cin >> ival, !cin.eof()) {
        // cout << "Current Enter loop state is: " << cin.rdstate() << endl;

        if (cin.bad()) {
            // no catch so the terminate will be called
            throw runtime_error("IO Stream corrupted");
        }

        if (cin.fail()) {
            cerr << "bad data, try again: ";
            cin.clear(istream::failbit);
            // cout << "Current state is: " << cin.rdstate() << endl;
            continue;
        }

        // ok, print out this integer
        cout << "Input correct, your number is: " << ival << endl;
    }
}

這裡有兩個錯誤:

(1)在Linux,g++環境下,cin.clear(istream::failbit)並不能清除cin的fail狀態,儘管從clear函數的文檔上來看應該是可以的。沒辦法,我改成了cin.clear()就OK了

(2) 遺漏了cin.ignore這個句子或有相同效果的代碼。這是因為cin的fail狀態雖然被消除了,但是本次讀入的錯誤的使用者輸入,比如使用者輸入的是一 個字串,還存在於cin的buffer中,這樣,下次迴圈cin >> ival照樣出錯,於是這樣就形成了死迴圈。因為cin的buffer中始終存在著使用者第一次輸入的錯誤資料,於是while迴圈就一直繼續著。

後 來我加了這樣一句: cin.ignore(100000, '\n'); 就OK了。可以看ignore的文檔,代碼的意思是ignore buffer中從一開始到第一個\n為止的所有字元,第一個參數故意寫的很大,這是因為ignore的第一個參數表示ignore多少個字元,太小會導致 buffer中清除的不乾淨。

修改後的代碼如下:

Code: Select all
#include <iostream>
#include <stdexcept>
using namespace std;

int main(int argc, char **argv)
{
    int ival;
    // cout << "Begin state is: " << cin.rdstate() << endl;
    while (cin >> ival, !cin.eof()) {
        // cout << "Current Enter loop state is: " << cin.rdstate() << endl;

        if (cin.bad()) {
            // no catch so the terminate will be called
            throw runtime_error("IO Stream corrupted");
        }

        if (cin.fail()) {
            cerr << "bad data, try again: ";
            cin.clear();
            // Here cin's error condition state cannot be removed unless
            // we use cin.clear() directly
            // cin.clear(istream::failbit);

            // ignore current read wrong characters otherwise the loop
            // will go infinitely
            cin.ignore(11111111, '\n');
            // cout << "Current state is: " << cin.rdstate() << endl;
            continue;
        }

        // ok, print out this integer
        cout << "Input correct, your number is: " << ival << endl;
    }
}

順便附上本章的另外一個練習代碼,列印常值內容,使用了fstream:

Code: Select all
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

int main()
{
    ifstream input;
    vector<string> filelist;
    filelist.push_back("read.cc");
    filelist.push_back("fread.cc");
    filelist.push_back("dummy.cc");
    vector<string>::const_iterator it = filelist.begin();

    string s;
    // loop begin
    while (it != filelist.end()) {
        input.open(it->c_str());
        if (!input) {
            cout << "Open file " << *it << " failed, quit..." << endl;
            break;
        }

        cout << "Printing file " << *it << endl;
        while (getline(input, s))
            cout << s << endl;
        input.close();
        input.clear();
        ++it;
    }
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.