2013-04-05 44 views
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,这等于坏道。 Failbit尚未清楚,为什么?

+0

可能的重复[为什么下面的c + +代码保持输出“坏数据,再试一次”?](http://stackoverflow.com/questions/4297469/why-the-following-c-code-keeps-output- bad-data-try-again) – jerry 2015-02-16 12:46:29

回答

6

问题是f从不会从输入流中删除,所以cin >> ival一直试图一遍又一遍地读取它。

您需要跳过它。例如,请参阅How does istream::ignore() work?

+0

我得到了你的答案,但是当我用'cin.ignore(1000,'\ n');',问题再次出现。当我使用'cin.clear();'而不是'cin.clear(istream :: failbit);',“坏数据,再试一次”只出现一次。我认为'cin.clear();'清除失败状态,但'cin.clear(istream :: failbit);'没有,我无法解释为什么。 – Robert 2013-04-05 15:35:26

+0

@Robert'cin.clear()'是正确的,请参阅我的回答以获得解释。 – jerry 2013-04-23 21:00:41

1

虽然NPE关于不从流中删除违规数据的观点是正确的,但它不是唯一的(或最令人震惊的)问题。

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

确保您在ignore之前致电clear,否则后者将不起作用。最后,为防止任意长的无效条目,请将std::numeric_limits<int>::max()作为第一个参数传递给ignore

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

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++入门,我不能说。我没有看过这本书,但我知道这是相当好的想法。我建议检查你的版本有多旧,并寻找勘误表。