【问题标题】:interrogating and controlling state of the stream询问和控制流的状态
【发布时间】:2017-07-12 16:08:10
【问题描述】:

我现在正在学习 C++ Primer 第 4 版并玩 IO 流。当我尝试运行书中的代码时(第289页):

#include <iostream>
#include <string>
using namespace std;
int main()
{
    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()){
            cerr << "bad data, try again\n";
            cin.clear(istream::failbit);
            continue;
        }
        //ok to process ival
    }
}

我在输入一个字符串(比如“as”)后遇到了一个无限循环。那么这段代码有什么问题呢?

【问题讨论】:

  • 你说的是“C++ Primer 4th edition”。请提供作者姓名(最好是 ISBN)来消除歧义

标签: c++ c++14


【解决方案1】:

当您输入一个字符串时,提取到ival 失败并且设置了failbit。然后,您尽职尽责地尝试清除该位并继续。但是该字符串仍在缓冲区中!所以这个动作永远重复。

此外,you didn't actually clear the bit; you just set the stream state to failbit

您只需调用std::cin.clear(),然后在继续之前从缓冲区中提取意外数据。

另外,while (cin &gt;&gt; ival, !cin.eof()) 是奇数;我没有检查行为或优先级,但我猜你会写while ((cin &gt;&gt; ival) &amp;&amp; !cin.eof())

总之,如果这真的是书中的代码,那么您需要一本更好的书,因为代码在几个严重的方面是错误的。如果你真的在编写 C++14,那么无论如何你都需要一本更新的书,因为 Lippman 的 C++ Primer 直到第 5 版才针对 C++11 进行了更新。

【讨论】:

  • 我刚刚尝试用 cin.clear() 替换 cin.clear(istream::failbit) 但它仍然没有用。那么如何清除缓冲区呢?我知道这本书很旧,但它仍然有帮助。对于逗号,我认为“a,b”是一个返回 b 的表达式。
  • @GuojunZhang:是的,你必须做我说的所有事情,而不仅仅是一部分
  • @GuojunZhang:是的,a, b 的计算结果为b,但a &lt;&lt; b, c 可能不会完全符合您的预期;取决于&lt;&lt;, 之间的关系。我现在没时间检查,我最喜欢的表情检查工具已经下线:( (geordi --precedence &lt;expr&gt;)
  • 我猜 while ((cin >> ival) && !cin.eof()) 没有帮助,因为当您输入字符串时 cin >> ival 自动失败,这不是程序的目标.
  • 没关系,我觉得这段代码已经过时了,所以我放弃了。
【解决方案2】:

最后通过添加 cin.ignore(INT_MAX, '\n') 使其工作。此行是必要的,因为 cin.clear() 仅在数据保留在缓冲区中时删除错误标志。为了清除缓冲区,需要 cin.ignore。

#include <iostream>
#include <string>
using namespace std;
int main()
{
    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()){
            cerr << "bad data, try again" << endl;
            cin.clear();
            cin.ignore(INT_MAX, '\n');
        }
        //ok to process ival
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 2020-06-21
    • 1970-01-01
    • 2019-07-16
    相关资源
    最近更新 更多