Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this stringstream fail when parsing into double?

I have the following code:

#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;
}

I want to parse a double and stop when an invalid character is hit. Here I try to parse "1_" and "1i", both of which should give me the double with value: 1.

here is my output:

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

So the stod function worked as expected, however the stringstream method did not. It makes no sense to me that 2 standard methods of parsing double, both in the standard library would give different results?

Why does the stringstream method fail when parsing: "1i"?

Edit:

this appears to give different results for some people. My compiler info is the following:

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

Edit2:

Is this a bug with libc++, or is the specification just vague about what counts as valid parsing for a double?

like image 577
Theo Walton Avatar asked Oct 28 '18 02:10

Theo Walton


1 Answers

This is a libc++ bug. Per [facet.num.get.virtuals] bullet 3.2, a character is only supposed to be accumulated if it is allowed as the next character of the input field of the conversion specifier determined in stage 1 (%g for double). Having accumulated 1, i is not allowed, so stage 2 should terminate.

libc++ is accumulating characters indiscriminately until it reaches a non-atom character (it also extended the atoms to include i, which is required to parse inf).

like image 122
T.C. Avatar answered Oct 16 '22 13:10

T.C.