Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't the EOF character work if put at the end of a line?

I'm learning C++ and trying to understand,
Why doesn't the EOF character (Ctrl + Z on Windows) break the while loop if put at the end of a line?

My code:

    int main() {
        char ch;
        while(cin >> ch) {
            cout << ch;
        }
    }

When I enter ^Z, the loop breaks;
But when I enter 12^Z, it doesn't.

like image 281
Cutter Avatar asked Jul 07 '12 21:07

Cutter


2 Answers

The C and C++ standards allow text streams to do quite Unholy things in text mode, which is the default. These Unholy Things include translation between internal newline markers and external newline control characters, as well as treating certain characters or character sequences as denoting end of file. In Unix-land it's not done, but in Windows-land it's done, so the the code can relate only to the original Unix-land conventions.

This means that in Windows, there is no way to write a portable C or C++ program that will copy its input exactly to its input.

While in Unix-land, that's no problem at all.

In Windows, a line consisting of a single [Ctrl Z] is by convention an End Of File marker. This is so not only in the console, but also in text files (depending a bit on the tools). Windows inherited this from DOS, which in turn inherited the general idea from CP/M.

I'm not sure where CP/M got it from, but it's only similar, not at all the same!, as Unix' [Ctrl D].

Over in Unix-land the general convention for end of file is just "no more data". In the console a [Ctrl D] will by default send your typed text immediately to the waiting program. When you haven't typed anything on the line yet, 0 bytes are sent, and a read that returns 0 bytes has by convention encountered end-of-file.

The main difference is that internally in Windows the text end of file marker is data, that can occur within a file, while internally in Unix it's lack of data, which can't occur within a file. Of course Windows also supports ordinary end of file (no more data!) for text. Which complicates things – Windows is just more complicated.


#include <iostream>
using namespace std;

int main()
{
    char ch;
    while(cin >> ch) {
        cout << 0+ch << " '" << ch << "'" << endl;
    }
}
like image 155
Cheers and hth. - Alf Avatar answered Oct 26 '22 12:10

Cheers and hth. - Alf


You won't find an answer to your question in the C++ standard.

cin >> ch will be a "true" condition as long as there's neither an end-of-file condition nor an input error. How an end-of-file condition is triggered is not specified by the language, and it can and will vary from one operating system to another, and even with configuration options in the same OS. (For example, Unix-like systems use control-D by default, but that can be altered by the stty command.)

Windows uses Control-Z to trigger an end-of-file condition for a text input stream; it just happens not to do so other than at the beginning of a line.

Unix behaves a bit differently; it uses Control-D (by default) at the beginning of a line, or two Control-Ds in the middle of a line.

For Unix, this applies only when reading from a terminal; if you're reading from a file, control-D is just another non-printing character, and it doesn't trigger an end-of-file condition. Windows appears to recognize control-Z as an end-of-file trigger even when reading from a disk file.

Bottom line: Different operating systems behave differently, largely for obscure historical reasons. C++ is designed to work with any of these behaviors, which is why it's not specific about some of the details.

like image 41
Keith Thompson Avatar answered Oct 26 '22 10:10

Keith Thompson