0

I am reading in from an input file "input.txt" which has the string 'ABCDEFGH' and I am reading it in char by char. I am doing this using the code:

ifstream plaintext (input.txt);
char ch;
if (plaintext.is_open())
{
    while(!plaintext.eof()){
        plaintext.get(ch);
        cout<<ch<<endl;
    }
    plaintext.close();
}

The string 'ABCDEFGHH' is printed out. I have no idea why it is printing 'H' twice. Any help would be appreciated. I got this code example from HERE

Sean Mann
  • 27
  • 5
  • 3
    Possible duplicate of [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). The example code in the link is terrible, learn from one of the books posted [here](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – user657267 Sep 18 '15 at 05:15
  • Ah, thank you. I changed my code to plaintext>>ch and it worked. I suppose I do not need to use plaintext.get() then? – Sean Mann Sep 18 '15 at 05:22
  • That will skip whitespace (unless you turn it off), `>>` is for formatted input, it all depends on what you want. `while (plaintext.get(ch))` will also work, and will read each byte of the file (unless you're on windows and the file's opened in text mode). The `is_open` check is redundant too because the stream will fail if the file isn't open, and `close` is also redundant because streams are closed automatically when they are destroyed, so the whole example could be `for (char c; plaintext.get(c); ) std::cout.put(c);` or even just `std::cout << plaintext.rdbuf(); ` – user657267 Sep 18 '15 at 05:42

1 Answers1

2

This is because the EOF test does not mean "our crystal ball tells us that there are no more characters available in this tream". Rather, it is a test which we apply after an input operation fails to determine whether the input failed due to running out of data (EOF) or some other condition (an I/O error of some sort).

In other words, EOF can be false even after we have successfully read what will be the last character. We will then try to read again, and this time get will fail, and not overwrite the existing value of ch, so it still holds the H.

Streams cannot predict the end of the data because then they could not be used for communication devices such as serial lines, interactive terminals or network sockets. On a terminal, we cannot tell that the user has typed the last character they will ever type. On a network, we cannot tell that the byte we have just received is the last one. Rather, we know that the previous byte was the last one, because the current read operation has failed.

Kaz
  • 48,579
  • 8
  • 85
  • 132