3

This simple code:

#include <iostream>
#include <sstream>
int main()
{
   float x = 0.0;
   std::stringstream ss("NA");
   ss >> x;

    std::cout << ( ss.eof() ? "is" : "is not") << " at eof; x is " << x << std::endl;
}

returns different results, depending on which library I choose (I'm running clang from xcode 5 on OSX 10.9):

clang++ -std=c++11 -stdlib=libstdc++ -> not at eof
clang++ -stdlib=libstdc++ -> not at eof
/usr/bin/g++-4.2 -> not at eof

clang++ -std=c++11 -stdlib=libc++ -> at eof
clang++ -stdlib=libc+ -> at eof

It seems to me that if I try to read an alphabetic character into a float, the operation should fail, but it shouldn't eat the invalid characters - so I should get fail() but not eof(), so this looks like a bug in libc++.

Is there a c++ standard somewhere that describes what the behavior should be?

p.s. I've expanded the original test program like so:

#include <iostream>
#include <sstream>
int main()
{
   float x = 0.0;
   std::stringstream ss("NA");
   ss >> x;
    std::cout << "stream " << ( ss.eof() ? "is" : "is not") << " at eof and " << (ss.fail() ? "is" : "is not") << " in fail; x is " << x << std::endl;
    if (ss.fail())
    {
        std::cout << "Clearing fail flag" << std::endl;
        ss.clear();
    }
   char c = 'X';
    ss >> c;
    std::cout << "Read character: \'" << c << "\'" << std::endl;
}

and here's what I see:

With libc++:

stream is at eof and is in fail; x is 0
Clearing fail flag
Read character: 'X'

with stdlibc++:

stream is not at eof and is in fail; x is 0
Clearing fail flag
Read character: 'N'

p.p.s. As described in the issue that n.m. links to, the problem doesn't occur if the stringstream is set to "MA" instead of "NA". Apparently libc++ starts parsing the string, thinking it's going to get "NAN" and then when it doesn't, it gets all upset.

Betty Crokker
  • 3,001
  • 6
  • 34
  • 68
  • This is the same issue as described [here](http://stackoverflow.com/questions/19725070/discrepancy-between-istreams-operator-double-val-between-libc-and-libstd/19727956#19727956). – n. m. could be an AI Mar 06 '14 at 19:26
  • n.m., I had looked at that issue, it looks exceedingly similar but since my problem was with eof() and the other issue complained about fail() I wasn't sure if the underlying problem was the same. Looking at the bug which was submitted for that other issue, it's unclear whether fixing that bug would solve my problem too ... but you know the inner workings of the libraries 100x better than I do! – Betty Crokker Mar 06 '14 at 19:41
  • This is the same problem, namely, whether `NA` is *consumed* by the failed input operation or not. – n. m. could be an AI Mar 06 '14 at 19:43

1 Answers1

2

In this case, you should get fail, but not eof. Basically, if, after failure, you can clear the error and successfully do a get() of a character, you should not get eof. (If you cannot successfully read a character after clear(), whether you get eof or not may depend on the type you were trying to read, and perhaps in some cases, even on the implementation.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • It's not so clear. "NA" is a prefix of "NAN". libc++ supports reading "NAN" from a stream, libstdc++ does not. – n. m. could be an AI Mar 06 '14 at 20:26
  • @n.m.Good point. However, the standard is clear. Inputting into a numeric type, only characters in the set `"0123456789abcdefxABCDEFX+-"`, plus the (locale dependent) decimal point and thousands separator are allowed to be extracted from the stream. This may be an oversight (in C, `fscanf` is allowed to read NaNs and infinities), but that's the way the standard currently reads. (From a QoI point of view, _if_ an implementation decides to support NaNs and infinities, it should at least take steps to ensure that the characters aren't extracted if there is no match. Or try to. – James Kanze Mar 07 '14 at 09:26
  • @n.m. Should this be considered an error in the standard? There's no `P`, either, which may occur in inputting a hex floating point. This is a serious issue, because it means that `fscanf( fin, "%f", &float_value )` may give different results (and extract more characters) than `fin >> float_value`, even when both succeed. – James Kanze Mar 07 '14 at 09:39
  • Yes I also thought "where is P" immediately upon seeing this list. I think it's an error in the standard. – n. m. could be an AI Mar 07 '14 at 11:48
  • @n.m. Since the goal is to offer the same possibilities as `fscanf`, not allowing `NaN` or `Infinity` is also an error. (Of course, in this case, it will fail in C++, rather than just giving different results. So maybe the intent is for it to fail immediately, and require the user to then get a word, and compare it himself.) – James Kanze Mar 07 '14 at 12:06