Question

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?

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top