0

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
3
  • How do you know it "doesn't seem to work right.." ? What does it seem to do ? Unrelated: what is this: = {player1, player2, player3}; doing on the end of your players array declaration? It isn't needed. Commented Nov 28, 2013 at 20:42
  • When I say it doesn't work right, I should specify that my debugger shows that the values in the struct aren't being updated correctly. Also, that is how I learned to initialize the array. Why is it not needed? Commented Nov 28, 2013 at 20:53
  • Without seeing player1 etc... it may be presumptive to say it isn't needed, but if they're simply declared as Quarterback player1, player2, player3; or some such, then it isn't needed. Those Quarterback objects in the array will construct all by themselves. But I'm curious, are you expecting player1, etc... to be updated by your read-code? If so, that is definitely not happening. You're reading into the array, not the playerN objects, on the off-chance you were intending the latter. Commented Nov 28, 2013 at 20:58

2 Answers 2

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];
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Much appreciated for reminding me of naming. I can get lazy sometimes.
1

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.

1 Comment

Appreciate the reminder about checking if my file is open, as well as seeing my mistake in the loops. Silly mistakes seem to become more frequent the more complex a program becomes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.