为什么将字符串流解析为双精度浮点数时会失败?

5
我看到了如下的代码:
#include <string>
#include <iostream>
#include <sstream>

int main()
{
        size_t x, y;
        double a = std::stod("1_", &x);
        double b = std::stod("1i", &y);

        std::cout << "a: " << a << ", x: " << x << std::endl;
        std::cout << "b: " << b << ", y: " << y << std::endl;

        std::stringstream s1("1_");
        std::stringstream s2("1i");

        s1 >> a;
        s2 >> b;

        std::cout << "a: " << a << ", fail: " << s1.fail() << std::endl;
        std::cout << "b: " << b << ", fail: " << s2.fail() << std::endl;
}

我想解析一个double类型的数,在遇到无效字符时停止。在这里,我尝试解析"1_""1i",两者都应该给我值为1的double类型。

这是我的输出结果:

a: 1, x: 1
b: 1, y: 1
a: 1, fail: 0
b: 0, fail: 1

所以,stod 函数按预期工作,但 stringstream 方法没有。对我来说,使用标准库中解析 double 的 2 种标准方法会产生不同的结果没有意义?
为什么 stringstream 方法在解析 "1i" 时失败?
编辑:
看起来这会为某些人提供不同的结果。我的编译器信息如下:
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

编辑2:

这是libc ++的错误,还是规范只是关于什么算作double有效解析的含义模糊不清?


@J.Doe 我打印了s2.fail(),它输出了1...这肯定意味着它失败了。 - Theo Walton
那么你使用的代码与此处展示的不同。 - user10543939
当我按照您发布的代码片段完全运行时,最后一行是 b: 1, fail: 0。我投票将此问题标记为无法重现的离题问题。 - Joseph Sible-Reinstate Monica
2
这是重现链接:https://wandbox.org/permlink/0qZ3Vd2nWThsE2Z6。看起来问题可能是因为在Linux上使用的是libc++而在MacOS上使用的是libstdc++。 - chris
2
是的,这是一个已知的libc++ bug。 - T.C.
显示剩余9条评论
1个回答

7
这是一个 libc++ bug。根据 [facet.num.get.virtuals] bullet 3.2,只有当一个字符被允许作为转换说明符输入域的下一个字符时(对于 double%g),它才应该被累积。由于已经累积了 1,而 i 不被允许,因此第二阶段应该终止。 libc++ 在累积字符时不加区分地进行,直到遇到非原子字符(它还扩展了原子包括需要解析 inf 的 i)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接