Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test whether stringstream operator>> has parsed a bad type and skip it

I am interested in discussing methods for using stringstream to parse a line with multiple types. I would begin by looking at the following line:

"2.832 1.3067 nana 1.678" 

Now lets assume I have a long line that has multiple strings and doubles. The obvious way to solve this is to tokenize the string and then check converting each one. I am interested in skipping this second step and using stringstream directly to only find the numbers.

I figured a good way to approach this would be to read through the string and check if the failbit has been set, which it will if I try to parse a string into a double.

Say I have the following code:

string a("2.832 1.3067 nana 1.678");   stringstream parser;  parser.str(a);   for (int i = 0; i < 4; ++i)  {      double b;      parser >> b;      if (parser.fail())      {          std::cout << "Failed!" << std::endl;          parser.clear();      }      std::cout << b << std::endl;  } 

It will print out the following:

2.832 1.3067 Failed! 0 Failed! 0 

I am not surprised that it fails to parse a string, but what is happening internally such that it fails to clear its failbit and parse the next number?

like image 539
Fantastic Mr Fox Avatar asked Jul 01 '14 07:07

Fantastic Mr Fox


People also ask

How do you check if a Stringstream is empty?

myStream. rdbuf()->in_avail() can be used to get the count of available characters ready to be read in from a stringstream , you can use that to check if your stringstream is "empty." I'm assuming you're not actually trying to check for the value null .

What does Stringstream clear do?

The clear() member function is inherited from ios and is used to clear the error state of the stream, e.g. if a file stream has the error state set to eofbit (end-of-file), then calling clear() will set the error state back to goodbit (no error). For clearing the contents of a stringstream , using: m. str("");

What is the difference between Stringstream and Istringstream?

A stringstream is an iostream object that uses a std::string as a backing store. An ostringstream writes to a std::string . An istringstream reads from a std::string . You read & write from & to an istringstream or ostringstream using << and >> , just like any other iostream object.

What does Stringstream mean in C++?

A stringstream class in C++ is a Stream Class to Operate on strings. The stringstream class Implements the Input/Output Operations on Memory Bases streams i.e. string: The stringstream class in C++ allows a string object to be treated as a stream. It is used to operate on strings.


1 Answers

The following code works well to skip the bad word and collect the valid double values

istringstream iss("2.832 1.3067 nana 1.678"); double num = 0; while(iss >> num || !iss.eof()) {     if(iss.fail()) {         iss.clear();         string dummy;         iss >> dummy;         continue;     }     cout << num << endl; } 

Here's a fully working sample.


Your sample almost got it right, it was just missing to consume the invalid input field from the stream after detecting it's wrong format

 if (parser.fail()) {      std::cout << "Failed!" << std::endl;      parser.clear();      string dummy;      parser >> dummy;  } 

In your case the extraction will try to read again from "nana" for the last iteration, hence the last two lines in the output.

Also note the trickery about iostream::fail() and how to actually test for iostream::eof() in my 1st sample. There's a well known Q&A, why simple testing for EOF as a loop condition is considered wrong. And it answers well, how to break the input loop when unexpected/invalid values were encountered. But just how to skip/ignore invalid input fields isn't explained there (and wasn't asked for).

like image 106
4 revs Avatar answered Sep 28 '22 07:09

4 revs