Reading from a file into an array of structs

2019-06-14 08:15发布

问题:

First off, I would like to say that this is an assignment for my CS161 class, so while a direct answer would be nice, a nice explanation will help me more than anything. We have covered structs this week, but I am having trouble with some of my code. My goal right now for the program is to read from a file called "QBInfo.txt" into an array of three structures.

struct QuarterBack{
    string name;
    int completions[kNumGames];
    int attempts[kNumGames];
    int yards[kNumGames];
    int touchdowns[kNumGames];
    int interceptions[kNumGames];
};

QuarterBack players[kNumPlayers] = {player1, player2, player3};

Also, if it helps I should say that kNumPlayers is a constant set to 3, and kNumGames is a constant set to 10.

This is the code I am using to read from my file. It doesn't seem to work right though, and I have been at a loss as to why, so I figured I might ask the community for some help.

ifstream myIF;
    myIF.open("QBInfo.txt");
    string trash;
    string temp;
    getline(myIF, trash);
    for(int i = 0; i < kNumPlayers; i++){
        getline(myIF, temp);
        players[i].name = temp;
        for(int j = 0; i < kNumGames; j++){
            myIF >> players[i].completions[j];
            myIF >> players[i].attempts[j];
            myIF >> players[i].yards[j];
            myIF >> players[i].touchdowns[j];
            myIF >> players[i].interceptions[j];
        }
    }

Here is the test case file that my instructor has provided. The first number is for a challenge portion of the assignment that I will be attempting later due to time restrictions. It is the reason for the getline(myIF, trash) portion of code before my loop begins.

3
Peyton Manning              
27  42  462 7   0
30  43  307 2   0
32  37  374 3   0
28  34  327 4   0
33  42  414 4   1
28  42  295 2   1
29  49  386 3   1
30  44  354 4   3
25  36  330 4   0
24  40  323 1   0
Tom Brady               
29  52  288 2   1
19  39  185 1   0
25  36  225 2   1
20  31  316 2   0
18  38  197 0   1
25  43  269 1   1
22  46  228 0   1
13  22  116 1   1
23  33  432 4   0
29  40  296 1   1
Drew Brees              
26  35  357 2   1
26  46  322 1   2
29  46  342 3   1
30  39  413 4   0
29  35  288 2   0
17  36  236 2   1
26  34  332 5   0
30  51  382 2   2
34  41  392 4   0
30  43  305 1   1

回答1:

Use istringstream to populate the structure members with the data read from the file. Naming may not be particularly important in a short program such as this - but it's a good habit to think about variable names that convey meaning. The data file appears to have the number of players in the first line. getline was used to read past this line. Normally that would be used to initialise a number-of-players variable.

std::ifstream infile;
infile.open("qb.dat");
std::string nPlayers;
std::string playerName;

getline(infile, nPlayers);
getline(infile, playerName);

for (int player = 0; player < kNumPlayers; ++player)
{
  for (int game = 0; game < kNumGames; ++game)
  {
    std::string dataRow;
    getline(infile, dataRow);
    std::istringstream is(dataRow);
    is >> players[player].completions[game] >>
          players[player].attempts[game] >>
          players[player].yards[game] >>
          players[player].touchdowns[game] >>
          players[player].interceptions[game];
  }
}


回答2:

What exactly isn't working out right with your program?

For one thing in the second for loop there's an error i < kNumGames instead of j < kNumGames.

Then you should at least check wether the file was successfully opened at all:

if( !myIF )
{
    // open failed
    return 1;
}

Then there is a problem with the line getline(myIF, temp);. It will only work the first time, because the second time you reach that line your reading position will be just after the last number you've read in and before the newline character. That is the second getline call will return an empty string and then you will try to read in numbers from the players name instead.

You can quickly fix that by adding getline(myIF, trash); after the inner for loop.