简体   繁体   中英

Inconsistent behavior when parsing numbers from stringstream on different platforms

In a project i'm using a stringstream to read numeric values using the operator>>. I'm now getting reports indicating that the parsing bahaviour is inconsistent across different platforms if additional characters are appended to the number (for instance "2i"). Compiling the sample below with GCC/VCC/LLVM on Linux results in:

val=2; fail=0

Compiling and running it on iOS with either GCC or LLVM reportedly yields:

val=0; fail=1

What does the standard say about the behavior of operator>> in such a case?

--- Sample Code ---------------------------------------------

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

According to this reference :

在此处输入图片说明

Thus, in either case:

  • if your compiler is pre C++11 and reading fails it would leave the value of val intact and flag failbit with 0.

  • if you compiler is post C++11 and reading fails it would set the value of val equal to 0 and flag failbit with 0.

  • However, operator>> extracts and parses characters sequentially with function num_get::get [ 27.7.2.2.2 Arithmetic extractors ], from the stream as long as it can interpret them as the representation of a value of the proper type.

  • Thus, in your case operator>> will call num_get::get for the first character (ie, 2 ) and the reading will succeed, then it will move on to read the next character (ie, i ). i doesn't fit a numerical value and consequently num_get::get will fail and reading will stop. However, there are already valid characters been read. These valid characters will be processed and assigned to val , the rest of the characters will remain in the stringstream . To illustrate this I'll give an example:


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

Output:

val=2; fail=0

i

  • You see that if I use extract operator again to a std::string , the character i is extracted.

  • The above however, doesn't explain why you don't get the same behaviour in ios.

This is a known bug with libc++ that was submitted to Bugzilla . The problem as I see it is with std::num_get::do_get() 's double overload somehow continuing to parse the characters a, b, c, d, e, f, i, x, p, n and their captial equivalents despite those being invalid characters for an integral type (other than e where it denotes scientific notation but must be followed by a numeric value otherwise failure). Normally do_get() would stop when it finds an invalid character and not set failbit as long as characters were sucessfully extracted (as explained above).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM