在不同平台上解析来自stringstream的数字时的行为不一致

时间:2014-06-03 07:28:32

标签: c++ ios gcc stringstream

在一个项目中,我使用字符串流来使用运算符>>来读取数值。我现在得到的报告表明,如果在数字后附加了附加字符,解析行为在不同平台上是不一致的(例如" 2i")。在Linux上使用GCC / VCC / LLVM编译下面的示例会导致:

VAL = 2;失败= 0

据报道,在iOS上使用GCC或LLVM编译并运行它会产生:

VAL = 0;失败= 1

该标准对运营商>>的行为有何评价?在这种情况下?

---示例代码------------------------------------------ ---

#include <sstream>
#include <iostream>

int main(int argc, const char **args)
{
  double val;
  std::stringstream ss("2i"); 
  ss >> val;
  std::cout << "val=" << val << "; fail=" << ss.fail() << std::endl;
  return 0;
}

2 个答案:

答案 0 :(得分:0)

根据reference

enter image description here

因此,在任何一种情况下:

  • 如果您的编译器是C ++ 11之前且读取失败,则会保留val的值,并将failbit标记为0。

  • 如果您的编译器是C ++ 11后发布且读取失败,则会将val的值设置为0并将failbit标记为0。

  • 但是,operator>>从流中依次提取和解析字符{{3>} [ 27.7.2.2.2算术提取器],只要它可以将它们解释为正确类型值的表示。

  • 因此,在您的情况下,operator>>将为第一个字符(即num_get::get)调用2并且读数将成功,然后它将继续阅读下一个字符(即i)。 i不符合数值,因此num_get::get将失败,阅读将停止。但是,已经读取了有效字符。这些有效字符将被处理并分配给val,其余字符将保留在stringstream中。为了说明这一点,我将举例说明:


#include <sstream>
#include <iostream>
#include <string>

int main(int argc, const char **args)
{
  double val(0.0);
  std::stringstream ss("2i");

  ss >> val;

  std::cout << "val=" << val << "; fail=" << ss.fail() << std::endl;

  std::string str;
  ss >> str;
  std::cout << str << std::endl;

  return 0;
}

输出:

  

VAL = 2;失败= 0

     

  • 您会看到,如果我再次对std::string使用提取运算符,则会提取字符i

  • 然而,上述内容并未解释您在ios中没有获得相同行为的原因。

答案 1 :(得分:0)

这是已提交给Bugzilla的已知的libc ++错误。我看到的问题是std::num_get::do_get()double重载以某种方式继续解析字符a, b, c, d, e, f, i, x, p, n及其等价数据,尽管这些字符是整数类型的无效字符(除了{{ 1}}其中它表示科学记数法,但必须后跟数值,否则失败)。通常e会在找到无效字符时停止,只要字符被成功提取就不会设置do_get()(如上所述)。

相关问题