views:

3517

answers:

5

I am parsing an input text file. If I grab the input one line at a time using getline(), is there a way that I can search through the string to get an integer? I was thinking something similar to getNextInt() in Java.

I know there has to be 2 numbers in that input line; however, these values will be separated by one or more white space characters, so I can't just go to a specific position.

+2  A: 

If the only thing in there is whitespace and integers, just try something like this:

int i1, i2;
stringstream ss(lineFromGetLine);
ss >> i1 >> i2;

or easier:

int i1, i2;
theFileStream >> i1 >> i2;
Eclipse
A: 

It's more than a little bit C-ish, but you could use sscanf() on the C string representation. Or you could use strtol() or relatives - also on the C string representation.

A more C++-ish way would probably use a string stream and an extractor.

Jonathan Leffler
A: 

I tried:

while (!inFile.eof()) {
 getline (inFile,inputLine);
 stringstream ss(inputLine);
 ss >> rows >> columns;
}

and I got the following error:

"term does not evaluate to a function taking 1 arguments" at line

ss(inputLine);

edit: so you have to declare the string stream at the moment you give it the paramater. Correctoed code edited above.

Tomek
BTW: Never loop on eof(), but on the read -> while(std::getline(....))
Luc Hermitte
+4  A: 

There are a couple of things to consider:
Lets assume you have two numbers on each line followed by text you don't care about.

while(inFile >> rows >> columns)
{
    // Successfully read rows and columns

    // Now remove the extra stuff on the line you do not want.
    inFile.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}

Also note if the only thing separating the integer values is "white space" then you don't even need to use the ignore() line.

The above while() works because: The operator >> returns a stream object (reference). Because the stream object is being used in a boolean context the compiler will try and convert it into a bool and the stream object has a cast operator that does that conversion (by calling good() on the stream).

The important thing to note is NOT to use the line

while(inFile.eof())

If you do use this then you fall into the trap of the last line problem. If you have read all the data eof() is still false (as it is not true until you try and read past EOF). So there is no data left in the file but you still enter the loop body. In your code the getline() is then executed and fails (no more data), EOF is now set. What the rest of the loop does will depend on how and where inLine is defined.

You can use this test as above. But you must also be willing to test the stream is OK after you have used it.

while(inFile.eof())  // Should probably test good()
{
    getLine(inFile,inputline);
    if(inFile.eof()) // should probably test good()
    {
         break;
    }
}
Martin York
You must *not* test good() and instead test fail(), which is same condition (except reversed) that `while (stream)` tests.
Roger Pate
@Roget Pate: If fail() is the inverse of good() why can we test good()?
Martin York
+1  A: 

Never use .eof() for testing whether you can read nor for testing whether the previous read failed. Both approaches will fail in certain situations because:

  • EOF is not set even when there are no characters left, if no read past the end has been attempted yet (e.g. after a getline of the last line, if there was a newline character at the end)
  • EOF is set even after a successful read if the read operation had to peek for the next character after the end to determine that it should stop reading (e.g. after a geline of the last line, if there was no newline character at the end)

In general you should ONLY use .eof() after a failed read to check if the failure was caused by end of input.

Use while (std::getline(...)) for looping over lines.

Tronic