views:

165

answers:

5

Why do I get an extra iteration (extra line printed) when this code completes? Does there need to be an extra newline at the EOF? I would prefer not having to add extra/special characters to mark the EOF.

#include <iostream>  
#include <fstream>  
#include <string>  
using namespace std;  

int main(){  
    ifstream infile("dictionary.txt"); // one word per line  
    string text;  
    while(infile){  
        infile >> text;  
        cout << text << endl;  
    }  
    infile.close();  
    return 0;  
}
+5  A: 

try

while(infile>>text) cout << text << endl;

instead.

Michael Krelin - hacker
That while condition really raises my hackles. I don't like side-effects - except, of course, for those special cases where I do. Anyway, I resisted the downvote for various reasons, and finally decided to upvote - not least because it's concise, simple, reliable and a common standard library idiom that everyone should understand. Even so... consider yourself growled at ;-)
Steve314
Thanks, Steve314, I don't mind being growled at. ;-) And, to be honest, when the side-effect is working code, I do like side-effects.
Michael Krelin - hacker
+3  A: 

With your while-condition you check whether the stream is in a good state. Then you read from the stream, which may or may not succeed. Then you output the value of text. What you should do is:

while(infile >> text){
    cout << text << endl;
}
sepp2k
+3  A: 

At the end of the file, infile might still evaluate to true, but the following extraction of a word with infile >> text fails. Even if it fails you still print out a line. A better way to do this would be to let the while loop check for successful extraction:

string text;
ifstream infile("dictionary.txt"); // one word per line  
while (infile >> text) {
    cout << text << endl;  
}
infile.close();
sth
+5  A: 

An input stream doesn't detect end-of-file until after you try to read past it. When you read the last word in the file, the input stream is still valid; on the next loop, infile >> text tries to read past EOF and fails, but the next line is still executed anyway.

The loop should look like this:

while (infile >> text)
    cout << text << endl;

This way EOF will be detected before it tries to write to the output.

Ross Smith
You have included the magic words about EOF. +1
Martin York
+1  A: 

You've already gotten a number of corrections, but perhaps a slightly different one is worth considering:

#include <iterator>
#include <iostream>
#include <string>
#include <fstream>

using namespace std; // not really a good idea, but harmless enough for now.

int main() { 
    ifstream infile("dictionary.txt");
    copy(istream_iterator<string>(infile), istream_iterator<string>(), 
        ostream_iterator<string>(cout, "\n"));
    return 0;
}
Jerry Coffin
+1 for the sake of diversity. I don't think it's particularly interesting in this case, though, because I doubt the idea is to copy words or push them into another iterator.
Michael Krelin - hacker