1

*Note: I'm using windows, so EOF is ctrl + Z for me.

For a while I've noticed an EOF input seems to behave differently in isolation than it does when accompanied by other input. For example, ^Z (the EOF command for windows in command prompt) and a^Z seem to cause different behavior in the following code:

#include <stdio.h>

#define MAX 1000

int getline(char s[]);

main() {

    int line;
    char arr[MAX];

    while( (line = getline(arr)) != EOF)
        printf("%s",arr);

    system("Pause");
    return 0;
}

int getline(char s[])
{
    int c, i = 0;

    while ((c = getchar()) != EOF && c != '\n') {
        s[i++] = c;
    }
    if (c == '\n') {
        s[i++] = c;
    }
    else
        return EOF;
    s[i] = '\0';
    return 1;
}

If I input ^Z + enter in the command prompt, the program predictably jumps to system("Pause"); However, if I input abc^Z + enter, nothing happens, as though EOF was ignored and a '\n' command was never received. If, at this point, I press enter again, it shows the following:

EOF weirdness

I've been tinkering with and debugging this code and small variations of it for over an hour now and can't seem to find anything wrong with it. In theory, if I input abc^Z + enter, I expect the input to be interpreted as abcEOF\n, which would give:

s[0] = 'a'
s[1] = 'b'
s[2] = 'c'
i = 3 when loop breaks from c = EOF
if (c == '\n') skipped since c = EOF
leads to else -> return EOF
in main(), line = EOF since that is what the function getline returned
while loop breaks because of above
system("Pause"); follows

Is there something wrong with my code that I'm overlooking or is there some quirk to EOF or command prompt that I should be aware of? I'm almost certain this isn't the only instance where mixing ^Z with other values caused unintended behavior.

ericgrosse
  • 1,490
  • 20
  • 37

2 Answers2

4

Don't think of CTRL-Z as the end-of-file character, there is actually a real character with code point 26 (which is what you'd normally expect CTRL-Z to generate).

Instead, think of CTRL-Z as a way for your terminal device to indicate the end of the input stream to your program. If you were to read a real file of the disk and it contained CTRL-Z, it should keep going (though that may not be the case in certain implementations where you, for example, open it with the mode r instead of rb).

In Windows, that translation of CTRL-Z to the end-stream operation only happens when it appears at the start of the line which is why you're not getting EOF when you enter abcCTRL-Z.

When you enter CTRL-Z on a character position that isn't the start of the line, it's treated as a real CTRL-Z, not a stream-closing operation. That's why you're getting that character, which is the printable character at code point 26.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • So there's no way to get the command prompt to process something like abcEOF or 89EOFbbc? – ericgrosse Jun 18 '13 at 06:50
  • No, not to my knowledge, Windows requires the CTRL-Z to be the first character on the line. There's nothing to stop you having a _file_ with only `abc` in it (no newline). – paxdiablo Jun 18 '13 at 06:50
  • +1, great answer *and* using the awesome keyboard markdown. Win-win. – unwind Jun 18 '13 at 08:18
  • Any reference about `CTRL-D` in UNIX? For the wikipedia(http://en.wikipedia.org/wiki/End-of-file ) say 'the driver converts a Control-D character at the start of a line into an end-of-file indicator' – Tony Aug 21 '14 at 07:44
  • @Tony, you're right. I thought I'd tested this but, testing now, it looks like it ignores CTRL-D unless it's at the start of a line. Fixed that section of the answer. – paxdiablo Aug 21 '14 at 09:26
  • What do you mean by saying 'ignores CTRL-D'? Printing the char of code 4? – Tony Aug 21 '14 at 09:29
  • @Tony, I mean if you execute `cat >qqq` and then enter keystrokes `a`, the first `` is ignored, at least under my Linux setup (as by examining the file with `od -xcb qqq`). Suggest you try it in your environment. – paxdiablo Aug 21 '14 at 11:04
  • Your test is rather like my this [question](http://stackoverflow.com/questions/25423614/gnu-getline-strange-behaviour-about-eof/25423841#25423841). Would you like to have a look for your response seems different another user's. – Tony Aug 23 '14 at 01:51
  • Tony, you seem to be fixating on the Unix side of things when the question was to do with Windows. Since that part of the answer was tangential at best, I've removed it. – paxdiablo Aug 23 '14 at 04:31
  • On POSIX systems, ctrl-D is treated just like \n -- that is, it terminates the `read` system call -- except that nothing is stored in the buffer. So, if you enter ctrl-D at the beginning of the line, `read` returns 0, which is treated as EOF. If you type abc^D, "abc" is read. – Jim Balter Aug 23 '14 at 04:40
0

It is the normal behaviour of getchar..

getchar() is a standard function and requires you to press *ENTER* to get the input

Many compilers/platforms support the non-standard getch() that does not require ENTER.

EOF is not a character. The EOF is a macro that getchar() returns when it reaches the end of input or encounters some kind of error

hazzelnuttie
  • 1,403
  • 1
  • 12
  • 22