【问题标题】:istream extraction operator: how to detect parse failure?istream 提取运算符:如何检测解析失败?
【发布时间】:2011-12-13 12:05:02
【问题描述】:

如何检测 istream 提取是否失败?

string s("x");
stringstream ss(s);
int i;
ss >> std::ios::hex >> i;

编辑——虽然问题标题涵盖了这一点,但我忘了在正文中提及:我真的想检测失败是由于格式错误,即解析,还是由于任何其他与 IO 相关的问题,以便提供适当的反馈(malformed_exception("x") 或其他)。

【问题讨论】:

标签: c++ parsing istream


【解决方案1】:
if(! (ss >> std::ios::hex >> i) ) 
{
  std::cerr << "stream extraction failed!" << std::endl;
}

就是这么简单。

ETA:下面是这个测试如何与流结束交互的示例。

int i;
std::stringstream sstr("1 2 3 4");
while(sstr >> i)
{
    std::cout << i << std::endl;
    if(sstr.eof())
    {
        std::cout << "eof" << std::endl;
    }
}

将打印
1
2
3
4
eof

如果您在 while 循环条件中检查 sstr.eof()sstr.good(),则不会打印 4。

【讨论】:

  • 谢谢;确实,它捕获了错误的解析。但是,它也会捕获任何其他bad() 情况(参见cplusplus.com/reference/iostream/ios/operator_voidpt)。我相信对sstr.rdstate() &amp; ios::failbit 的测试会更准确。
  • 如果你在while循环条件中检查sstr.eof(),将会打印4。
  • @ctn while(sstr&gt;&gt; i &amp;&amp; !(sstr.eof())) 将无法打印 4,我相信这是我在 2011 年写下我所做的事情时的想法。另一方面,while(!(sstr.eof()) &amp;&amp; sstr &gt;&gt; i) 或 @987654331 @ 将打印 4。现在来看,最后一个公式是更直观的阅读方式。
  • 是的,最后一个公式也是我的想法。检查错误时它似乎也更有用:while (!sstr.eof()) { if (!(sstr &gt;&gt; i)) { error("not a number"); } }
【解决方案2】:

提取值失败将设置流的“失败”位,可以通过if (ss.fail()) 或仅if (!ss) 检测到。等效地,您可以测试&gt;&gt; 操作的结果,因为它返回对流的引用。

这些也会检测设置“坏”位的其他错误;你可以用ss.bad()区分这些。

如果您想继续从流中读取,您需要清除状态标志 (ss.clear())。

【讨论】:

  • ss.bad()!ss 测试两个不同的东西。首先测试底层媒体故障(badbit),而其他测试则针对格式化输入故障(badbit | failbit)。
  • @wilx:是的,我把“坏”和“失败”搞混了。现已修复。
【解决方案3】:

提取过程中的错误由内部状态标志发出信号。 您可以通过good() 成员函数查看它们。 也可以在这里查看:http://www.cplusplus.com/reference/iostream/stringstream

或者只使用上面建议的if()-construction。 这是由于流类的布尔转换运算符而起作用的

【讨论】:

  • 感谢您的参考。如果您的答案被接受,您是否意识到您的答案超出了“上述建议”?
【解决方案4】:

首先:感谢您提供有用的答案。然而,经过一些调查(cfr.cppreference)和验证,似乎检查解析失败的一种方法是检查ios::failbit 标志,如

const bool parsing_failed = (ss >> ios::hex >> i).rdstate() & ios::failbit ;

虽然建议的istream::operator!istream::operator bool 混合failbit badbit(参见cplusplusreference 上的herethere)。

【讨论】:

  • 它看起来确实很复杂——我需要再看一遍才能理解它:(。是什么意思?
猜你喜欢
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-06
  • 2021-08-07
  • 2010-11-21
相关资源
最近更新 更多