• C++ Primer 4th中第八章的一个错误 遗漏了cin.ignore


    第八章有个例子,非常简单,就是读入用户输入,赋给一个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;
        }
    }
  • 相关阅读:
    报表打印
    MyGridControl
    用户控件制作时设计模式加载报错的解决办法
    代码生成工具
    上传控件的使用
    数据加密
    DevExpress介绍
    记一次手动安装pecl扩展memcache
    关于httpd.conf的一点随笔
    temp
  • 原文地址:https://www.cnblogs.com/super119/p/1996151.html
Copyright © 2020-2023  润新知