You may want to periodically check this file during the lab since tips may
be added to it as students ask questions about the lab.
- friend is a C++ keyword so do not try to declare a class or a
variable with the name friend.
- My example code uses cin to read from stdin while the lab
requires that you read from a file. You can use an ifstream
to declare a variable that will read from a file and the open
method to open the file. You will also need to include fstream
at the beginning of your code:
#include
#include
...
main(int argc, char *argv[]) {
ifstream input_file;
input_file.open(argv[1]);
if (!input_file) {
perror(argv[1]);
return 0;
}
... rest of your code ...
}
You use the >> operator to read input from an fstream,
just as you would from an iostream. If you do not understand this code,
try writing your program initially to read from stdin using
cin. I will go over the fstream code in class on Tuesday.
- If your parrot.cpp program is printing the last line of the
input twice, it might be due to how you are testing for end of
file. C++ has an annoying "feature" in that it does not know
that it has reached end-of-file when it reads the last line of
input. That is, when it reads the "barthowlomew" line in the
friends file, it does not realize that it has reached the end
of file and so the eof flag remains false. It is not until it
tries to read
the next line of input that it discovers that the input is
exhausted and that it sets the eof flag to true.
If you test for eof in the following manner, then your code may
print the last line of the input twice:
while (!inFile.eof())
{
inFile >> name >> num_correct >> num_answered;
... print input line ...
}
When this code reaches the last line of the file, the one with
"barthowlomew", it reads it and prints it normally. However, if you check
the eof flag after it has read the "barthowlomew" line, you will see that
it is still false. So when the while loop checks the condition, it enters the
loop one more time (one for the road so to speak). This time when it attempts
to read inFile, C++ realizes that the input is exhausted and sets the eof
flag to true. It also leaves the previous values of name/num_correct/num_answered
unchanged since the read failed.
Thus your code prints out the "barthowlomew" line twice.
There are three common fixes to this code:
- Use a "priming read" that reads/initializes the input variables before starting the loop:
inFile >> name >> num_correct >> num_answered;
while (!inFile.eof()) {
... print the input line ...
inFile >> name >> num_correct >> num_answered;
}
Notice that since the priming read initializes the input variables, I
need to move the file read operation from the beginning to the end of
the loop.
- Use a permanent true condition for the while loop and test for eof immediately after the read:
while (true) {
inFile >> name >> num_correct >> num_answered;
if (inFile.eof())
break;
... print the input line ...
}
- Put the read in the loop condition and test the return condition
(the solution I presented in class). This solution is a bit lazy
because the read could fail for other reasons than eof.