[C++]problem with getline

Started by
3 comments, last by rip-off 12 years, 11 months ago
Hi. I have a file with highscores which I want to open, read and close.

The file inside has 30 rows of data which are
name[0]
score[0]
date[0]
.
.
.
name[9]
score[9]
date[9]

So I am gathering input. I get a string (for the name), then an integer (score) and then another string (the date).
The date and maybe the name will have spaces inside them, so I want to use getline instead of the >> operator to read the strings correctly.

This is my code:

while( !in.eof() )
{
//in >> highscores.names; // read name
getline(in, highscores.names, '\n');
++counter;

in >> highscores.scores; // read score
++counter;

in >> highscores.dates; // read date
++counter;

++i;
}


This is just a test, to read the name using getline and the other two with the >> operator.
However, if I use getline, my program crashes! If I don't, it works (it works because the strings that I have inside the savefile haven't got spaces between them)

Why does it crash when I use getline? (The file opens correctly).
Advertisement

Why does it crash when I use getline? (The file opens correctly).


You should check the value on i when the program crashes, I would suspect getline is not reading your file like you think it is.
I would assume your writing data outside of your struct
The extraction (>>) operator will not read in the \n after date. So when getline is called, it reads in an empty string.

An example (with endlines shown as \n instead of whitespace):


John \n
300 \n
3/3/2011 \n
Ed \n
300 \n
3/4/2011 \n

Your code will read in the first set of data correctly, but this is what the file looks like after it is done:

\n
Ed \n
300 \n
3/4/2011 \n

So the next name will be "", the next score will be "Ed", and the next date will be "300". Obviously this isn't correct and will cause an error.

The extraction (>>) operator will not read in the \n after date. So when getline is called, it reads in an empty string.

An example (with endlines shown as \n instead of whitespace):


John \n
300 \n
3/3/2011 \n
Ed \n
300 \n
3/4/2011 \n

Your code will read in the first set of data correctly, but this is what the file looks like after it is done:

\n
Ed \n
300 \n
3/4/2011 \n

So the next name will be "", the next score will be "Ed", and the next date will be "300". Obviously this isn't correct and will cause an error.


Thank you, I have fixed it now =]

I put a dummy string which I read after operator >> .
Reading an dummy string is a brittle approach.

A different way of handling this is to not mix std::getline and operator>>. Use getline() for everything, then re-parse the data in memory as a non-string type using std::stringstream:

#include <sstream>
#include <iomanip>

// Helper function
bool convert_to(const std::string &text, int &number)
{
std::stringstream stream(text);
return (stream >> number && stream >> std::ws && stream.eof()); // Is the entire string a valid integer (barring whitespace)?
}

// Elsewhere...
std::string name, score, date;
while(std::getline(in, name) && std::getline(in, score) && std::getline(in, date))
{
HighScore &highScore = highscores;

highscore.name = name;
++counter;

if(!convert_to(score, highscore.score))
{
// handle error
}
++counter;

if(!convert_to(date, highscore.date))
{
// handle error
}
++counter;

++i;
}

Also note how this code has a lot more error handling than your original attempt. This is important whenever you are dealing with external information that could be easily corrupted.

This topic is closed to new replies.

Advertisement