I have a file containing data in the following form:
ballcolor 10
bgcolor 5
[...]
Which I'm trying to read via the following:
void read (const char *filename)
{
ifstream prefsfile (filename);
if (prefsfile.is_open ())
{
char prefsline [BUFSIZE], prefname [BUFSIZE];
unsigned int value;
while (! prefsfile.eof ())
{
prefsfile.getline (prefsline, BUFSIZE);
istringstream iss (prefsline);
iss >> prefname >> value;
if (! (iss.fail () || prefsfile.fail ()))
{
if (! strcmpi (prefname, PREFSTR_PAD_COLOR) && value <= BACKGROUND_MAX)
{
color.pad = value << 4;
}
else if (! strcmpi (prefname, PREFSTR_BALL_COLOR) && value <= FOREGROUND_MAX)
{
color.ball = value;
}
else if (! strcmpi (prefname, PREFSTR_FOREGROUND_COLOR) && value <= FOREGROUND_MAX)
{
color.foreground = value;
}
else if (! strcmpi (prefname, PREFSTR_BACKGROUND_COLOR) && value <= BACKGROUND_MAX)
{
color.background = value << 4;
color.ball |= color.background;
}
}
}
prefsfile.close ();
}
}
If I give it a file that exactly conforms to the format shown above, it works well. However, if the file doesn't conform, or if the length of each line is larger than BUFSIZE(=30)
, it goes in an infinite loop.
How do I resolve the problem?
You are checking for ! prefsfile.eof ()
but if you checked for the more generic prefsfile.good()
your loop should break if the line is longer than BUFSIZE
.
The getline reference explains when the failbit is set. In particular, if the delimiter is not found by the time BUFSIZE
characters have been read from the input.
I would read the file like this:
void read (const char *filename)
{
ifstream prefsfile (filename);
if (prefsfile.is_open ())
{
char prefsline [BUFSIZE], prefname [BUFSIZE];
unsigned int value;
while (prefsfile.getline(prefsline, BUFSIZE))
{
if (prefsfile.eof()) {
break;
}
istringstream iss (prefsline);
iss >> prefname >> value;
cout << prefname << " " << value << "\n";
}
prefsfile.close ();
}
}
If the line is too long, the while
loop condition will evaluate to false.
Test 1 - long line breaks the loop
ballcolor 10
really really long line that is over 30 characters
bgcolor 5
output:
ballcolor 10
Test 2 - shorter lines
ballcolor 10
bgcolor 5
output:
ballcolor 10
bgcolor 5