C++ reading a file into a struct

19.8k views Asked by At

Using fstreams I have a file opened that contains numerous lines. Each contiguos set of 4 lines are such that: the first line is an int, the second and third are strings and fourth is a double. This sequence continues till EOF.

I'm attempting to load these lines into a struct array:

struct Library {
    int id;
    string title;
    string artist;
    double price;
};

and the code I'm trying to implement to load data into the struct is this:

const int LIMIT = 10
Library database[LIMIT];
ifstream file;
file.open("list.txt");

if(file) {
    while(!(file.eof()) && counter < LIMIT) {
        file >> database[counter].id;
        getline(file, database[counter].title;
        getline(file, database[counter].artist;
        file >> database[counter].price;
    }
} else {
   ...
}

// Using the following to debug output
for(int i = 0; i < counter; i++) {
    cout << "ID:     " << database[i].id << endl
         << "Title:  " << database[i].title << endl
         << "Artist: " << database[i].artist << endl
         << "Price:  " << database[i].price << endl
         << "-----------------------" << endl;
}

The file I'm trying to throw at this thing is

1234
Never Gonna Give You Up
Rick Astley
4.5
42
Thriller
Michael Jackson
32.1

The problem I'm having here is that between reading the id and title using file >> ... and getline(...) is that somewhere a newline bite is being introduced screwing up the output, which displays this monstrosity...

ID:     1234
Title:  
Artist: Never Gonna Give You Up
Price:  0
--------------------
ID:     0
Title:  
Artist:
Price:  0
--------------------

The solution is probably the most basic of solutions, but mainly because I can't figure out exactly what is going on with the newline bite I can't combobulate a phrase to shove into google and do my stuff there, and I'm at the stage where I've been looking at a problem so long, basic knowledge isn't working properly - such as how to handle basic input streams.

Any form of help would be much appreciated! Thanks in advance :)

3

There are 3 answers

4
jaggedSpire On BEST ANSWER

This happens because the >> operator for the input stream only grabs part of a line, and does not always grab the newline character at the end of the line. When followed by a call to getline, the getline will grab the rest of the line previously parsed, not the line after it. There are a few ways to solve this: you can clear the buffer from the input stream after each read, or you can simply get all your input from getline and just parse the resulting strings into an integer or a double when you need to with calls to stoi or stod.

As a side note, you don't want to detect the end of your file the way you presently are. See why is eof considered wrong inside a loop condition?

5
Sid On

You can solve this problem by adding:

fflush(file);

everytime before you use getline(file, ...). Basically this will clear the input buffer before you use the getline() function. And fflush() is declared in the cstdio library.

0
David Harrison On
file >> database[counter].id;

will read, in this case, a whitespace separated sequence of characters that is interpreted as an int. The newline is considered whitespace. You should now be sitting on that newline character, thus the getline() will read nothing -- successfully -- and increment the file position just past that.

You may be better off using getline() for each line and then separately interpreting the lines from the reading. For example, the first line read could be interpreted with a subsequent std::stoi() to get the integer representation from the string.