Reputation: 45
I'm trying to read a double, followed by a character, from cin using the snippet:
double d;
char c;
while(1) {
cin >> d >> c;
cout << d << c << endl;
}
The peculiar thing is that it works for some characters, but not for others. For example, it works for "2g", "2h", but fails for "2a", "2b", "2x" ...:
mwmbp:ppcpp mwisse$ ./a.out
2a
0
2b
0
2c
0
2g
2g
2h
2h
2i
0h
2x
0h
2z
2z
As pointed out by one of you, it does indeed work for integers. Do you know why it doesn't work for doubles? I have as yet been unable to find information on how cin interprets its input.
Upvotes: 1
Views: 1902
Reputation: 38949
This is currently a bug on LLVM: https://llvm.org/bugs/show_bug.cgi?id=17782 Way back in 2014 it was assigned from Howard Hinnant to Marshall Clow since then... Well don't hold you breath on this getting fixed any time soon.
EDIT:
The istream
extraction operator internally uses num_get::do_get
Which sequentially performs these tasks for a double
:
double
that's %lg
ctype
or numpunct
facet
sscanf
would allow the character obtained from 3 to be appended to the input field given the conversion specifier obtained in 1, if so 3 is repeated if not 5 is performed on the input field without this characterdouble
from the accepted input field is read in with
failbit
is assigned to the istream
's iostate
, but if 5 succeeded, the result is assigned to the double
facet numpunct
in 3 their position is evaluated, if any of them violate the grouping
rules of the facet
, failbit
is assigned to the istream
's iostate
eofbit
is assigned to the istream
's iostate
That's a lot to say that for a double
you're really concerned with scanf
's %lg
conversion specifier's rules for extraction of a double
(which internally will depend upon strtof
's constraints):
Note that if your locale
defines any other expression as an acceptable floating point input field this is also accepted. So if you've added some special sauce to the istream
you're working with that may be where the problem lies. Outside of that, neither a trailing "a", "b", or "x" are an accepted suffix for the %lg
conversion specifier, so your implementation is not compliant or there's something else you're not telling us.
Here is a live example of your inputs succeeding on gcc5.1 which is compliant: http://ideone.com/nGGW0L
Upvotes: 1
Reputation: 45
Since the problem is caused by a bug (or feature, depending on your point of view), in libc++, it seems that the easiest way to avoid it is to use libstdc++ instead, until a fix is in place. If you're running on a mac, add -stdlib=libstdc++ to your compile flags. g++ -stdlib=libstdc++ test.cpp will correctly compile the code given in this post.
Libc++ appears to have other, similar, bugs, one of which I posted here: Trying to read lines from an ASCII file using C++ , Ubuntu vs Mac...?, before learning about these different libraries.
Upvotes: 0