Professional C__ - Marc Gregoire [469]
string temp;
getline(istr, temp);
printStreamState(istr);
cout << temp << endl;
mCitations[count] = temp;
}
}
}
Code snippet from ArticleCitations\CoutDebugging\ArticleCitations.cpp
When you run your program this time, you find some interesting information:
Enter a file name ("STOP" to stop): paper1.txt
readFile(): counting number of citations
stream state is good
Citation 0: Godel, "Uber formal unentscheidbare Satze der Principia Mathernatica und verwant der Systeme, I", Monatshefte Math. Phys., 38 (1931). 173-198.
stream state is good
Citation 1: Alonzo Church. "An unsolvable problem of elementary number theory", American J of Math., 58(1936), 345 363.
stream state is good
Citation 2: Alonzo Church. "A note on the Entscheidungsprob1em", J. of Symbolic logic, 1 (1930), 40 41.
stream state is good
Citation 3: Cf. Hobson, "Theory of functions of a real variable (2nd ed., 1921)", 87, 88.
stream state is eof
Citation 4: Proc. London Math. Soc (2) 42 (1936 7), 230 265.
Found 5 citations
readFile(): reading citations
stream state is fail
stream state is eof
stream state is fail
stream state is eof
stream state is fail
stream state is eof
stream state is fail
stream state is eof
stream state is fail
stream state is eof
Alan Turing,"On Computable Numbers with an Application to the Entscheidungsproblem", Proceedings of the London Mathematical Society, Series 2, Vol.42 (1936 - 37) pages 230 to 265.
[ 5 empty lines omitted for brevity ]
Enter a file name ("STOP" to stop):
It looks like the stream state is good until after the final citation is read for the first time. Then, the stream state is eof, because the end-of-file has been reached. That is expected. What is not expected is that the stream state is both fail and eof after all attempts to read the citations a second time. That doesn’t appear to make sense at first: The code uses seekg() to seek back to the beginning of the citations before reading them a second time, so the file shouldn’t still be at the end.
However, Chapter 15 explains that streams maintain their error and eof states until you clear them explicitly. seekg() doesn’t clear the eof state automatically. When in an error or eof state, streams fail to read data correctly, which explains why the stream state is fail also after trying to read the citations a second time. A closer look at your method reveals that it fails to call clear() on the istream after reaching the end of the file. If you modify the method by adding a call to clear(), it will read the citations properly.
Here is the corrected readFile() method without the debugging cout statements:
void ArticleCitations::readFile(const string& fileName)
{
// Code omitted for brevity
if (count != 0) {
// Allocate an array of strings to store the citations.
mCitations = new string[count];
mNumCitations = count;
// Clear the previous eof.
istr.clear();
// Seek back to the start of the citations.
istr.seekg(citationsStart);
// Read each citation and store it in the new array.
for (count = 0; count < mNumCitations; count++) {
string temp;
getline(istr, temp);
mCitations[count] = temp;
}
}
}
Code snippet from ArticleCitations\AfterCoutDebugging\ArticleCitations.cpp
Using the GDB Debugger on Linux
Now that your ArticleCitations class seems to work well on one citations file, you decide to blaze ahead and test some special cases, starting with a file with no citations. The file looks like this, and is stored in a file named paper2.txt:
Author with no citations
When you try to run your program on this file, you get the following result:
Enter a file name ("STOP" to stop): paper1.txt
[ correct output of reading paper1.txt omitted for brevity ]
Enter a file name ("STOP" to stop): paper2.txt
Author with no citations
Segmentation fault (core dumped)
The segmentation fault means that the program crashed. This time you decide to give the debugger a shot. The Gnu DeBugger (gdb) is widely available on Unix and Linux platforms. First, you must compile your program with debugging info (-g with g++).