A quick question: I have been writing a small program to simply read a file and send to cout.

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

int main() {
	char ch;
	ifstream in_stream;
	in_stream.open("self.cpp");
	
	while(!in_stream.eof()) {
		cout << ch;
		in_stream.get(ch);
	}
	
	in_stream.close();
	return 0;
}

This works ok, except that the last '}' of the file is printed twice.

However, if I reverse the order of lines 11 & 12 (so that in_stream.get is called before cout << ch), the last character of the file is printed only once so the program works correctly.

I cannot figure out the reason for this subtle difference. Could anybody help me?

Thanks.

Recommended Answers

All 3 Replies

A quick question: I have been writing a small program to simply read a file and send to cout.

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

int main() {
	char ch;
	ifstream in_stream;
	in_stream.open("self.cpp");
	
	while(!in_stream.eof()) {
		cout << ch;
		in_stream.get(ch);
	}
	
	in_stream.close();
	return 0;
}

This works ok, except that the last '}' of the file is printed twice.

However, if I reverse the order of lines 11 & 12 (so that in_stream.get is called before cout << ch), the last character of the file is printed only once so the program works correctly.

I cannot figure out the reason for this subtle difference. Could anybody help me?

Thanks.

its because the last call to in_stream.get(ch) stores the last character in the file. But probably its not the end of file yet, because it still have one more character: EOF. So the cout is again executed. But at this point, the character ch has the previous value it read from file since the very last read reads EOF and hence does not store in that variable which have its previous value intact.
That is why its printing the last character twice.

But that was not the very exact explanation though.

First of all I am suprised that the first code you works.
Reason? You did not initialize ch, yet you are able the output it the first time you do the while loop.

But I'll answer your question:
A while loops ends when the condition becomes false, but it finishes the current loop in which the condition became false. With the while loop you gave, the condition is that the stream pointer is not at the end of the file.

The streampointer is at the end of the file, when in_stream.get(ch) cannot read a new character (thus after the last character it read). I thought '\0' (non-character) comes right after the last character, but I am not sure on that point.

That's the theory, now the practice.

First I discuss this:

while(!in_stream.eof()) { // I call this x
    in_stream.get(ch); // I call this y
    cout << ch; // I call this z
}

When y reads the last '}', z outputs the last '}'. x is still true, because y previous read was succesful. Now y fails to read the next character (simply because it does not exist), so x is false. But it still has to z, to end the while loop. Most likely he did not change ch in y (because the character it tried to read did not exist) and so he outputs the last character again: '}'

Your first code is simply incorrect.

while(!in_stream.eof()) {
    cout << ch;
    in_stream.get(ch);
}

So I change it a bit and let's assume you used

char ch = ' '; // instead of char ch;
/*Yes, he will also output a ' ' in the beginning of the output, but we ignore that part*/

The last '}' is read in the previous while loop 'round'. He outputs '}' now and reads a non-character (so end of file), so the condition is false. While loops ends and he only outputted one '}'.

Long explanation indeed, but I hope you understand it now.

Otherwise ask again.

First of all I am suprised that the first code you works.
Reason? You did not initialize ch, yet you are able the output it the first time you do the while loop.

Yes u dint initialised your variable.
But

char ch = ' '; // instead of char ch;
/*Yes, he will also output a ' ' in the beginning of the output, but we ignore that part*/

This will print an extra character which is not there in your file. So its better to do it as u told u did by reversing the sequence of the two statements.

while(!in_stream.eof()) {	
      in_stream.get(ch);
      cout << ch;	
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.