Search code examples
c++parsingistream

How to read-and-validate from istringstream by fields


I am trying to check input validity. I am given a file, where there are two columns, first one of strings, second one of ints. The separator is any number of spaces. The problem is, I cannot figure out how to properly check if the second item really is an int. Consider this code:

string line; // parameter with a string to be parsed
string name;
int num;
istringstream lineStream(line);
lineStream >> name;
lineStream >> num;

by calling lineStream.good() I can detect inputs such as "abcd g", but when I put something like "abcd 12a" in, it is parsed to "abcd" and 12. Same with "abcd 12.2" etc.

In Java I could use String.split() to an array and then parse each whole element, not ignoring any characters, but I do not know what is the correct approach here.

Thanks for hints


Solution

  • You could simply check if you reached the end of the line std::stringstream after you've extracted the int. If the int extraction fails, there was no integer at all. If it succeeds but there is still content in the stream, then there is too much in the line. I would approach the problem like so:

    std::string line, name;
    int num;
    while (std::getline(file, line)) {
      std::stringstream line_stream(line);
      if (line_stream >> name >> num &&
          line_stream.eof()) {
        // Line was of the correct format
      }
    }
    

    Basically, there are two checks:

    1. line_stream >> name >> num will fail if it can't extract either the string or int.
    2. After these extractions, the eof bit will be set if they reached the end of the stream. So line_stream.eof() will fail if there is still content left in the stream.

    Obviously this is a pretty fragile method that only works for the particular situation and would need adapting to pretty much any change in line format.