1

我在一本书中找到了这个代码片段:

int ival;
// read cin and test only for EOF; loop is executed even if there are other IO failures
while (cin >> ival, !cin.eof()) {
    if (cin.bad())         // input stream is corrupted; bail out
        throw runtime_error("IO stream corrupted");
    if (cin.fail()) {                        // bad input
        cerr<< "bad data, try again";        // warn the user
        cin.clear(istream::failbit);         // reset the stream
        istream::iostate cin_state = cin.rdstate();
        continue;                            // get next input
    }
    // ok to process ival
}

如果我在命令窗口点击'f',那么无数“坏数据,重试”,cin_state为0X02,等于badbit。Failbit一直不清楚,为什么?

4

2 回答 2

6

问题是它f永远不会从输入流中删除,因此cin >> ival不断尝试一遍又一遍地读取它。

你需要跳过它。例如,请参阅istream::ignore( ) 如何工作?

于 2013-04-05T09:20:31.467 回答
1

虽然 NPE 关于不从流中删除违规数据的观点是正确的,但这并不是唯一(或最严重)的问题。

您应该使用cin.clear(),这与cin.clear(ios_base::goodbit)默认参数相同。正如您在评论中推测的那样,cin.clear(istream::failbit)不会重置cin为良好状态。事实上,它将流设置为失败状态。这似乎违反直觉,但clear将流的状态设置为(或“将其清除为”)传递的参数。关于其操作还有一些其他细节,但它们与本次讨论无关。

确保你调用clearbefore ignore,否则后者将不起作用。最后,为了防止任意长的无效条目,将std::numeric_limits<int>::max()toignore作为第一个参数传递。

修改后的代码片段应该是:

int ival;
// read cin and test only for EOF; loop is executed even if there are other IO failures
while (cin >> ival, !cin.eof()) {
    if (cin.bad())         // input stream is corrupted; bail out
        throw runtime_error("IO stream corrupted");
    if (cin.fail()) {                        // bad input
        cerr<< "bad data, try again";        // warn the user
        cin.clear();         // or cin.clear(istream::goodbit);
        istream::iostate cin_state = cin.rdstate();
        cin.ignore(std::numeric_limits<int>::max(), '\n');
        continue;                            // get next input
    }
    // ok to process ival
}

至于为什么你在 C++ Primer 中发现了这个,我不能说。我没有读过这本书,但我知道它的思想相当好。我建议检查您的版本的年龄并查找勘误表。

于 2013-04-23T18:45:01.887 回答