Why doesn't getchar() recognise return as EOF on the console?

I have a small snippet of code below that I'm running using PellesC.

When the code is executed and I've typed a few characters into the console, I press enter.

Can you explain to me why the printf("%ld\n", nc); line doesn't seem to get executed? As no output is written to the console.

#include <stdio.h>

int main(void)
{
    long nc = 0;

    while(getchar() != EOF)
    {
        ++nc;
    }

    printf("%ld\n", nc);
}

I've decided to learn C thoroughly using the K&R book and I'm embarrassed to say this rather elementary example has me stumped.


Pressing enter doesn't actually cause an EOF ("end of file"). You have to signal that you are completely finished with providing input; on Unix you typically do that by pressing CtrlD. On Windows I believe it's CtrlZ followed by enter, but I'm really not sure about that.


You will only get an EOF from the stream when the end of file is reached, not the end of line. How you signal an end of file depends on your OS and terminal settings.

It's usually CTRLd on UNIX-type systems and CTRLz on Windows. For UNIX in cooked mode (normal input mode), you'll generally have to enter it as the first character of a line and follow it with a newline (ENTER).

With Windows, the CTRLz can be entered anywhere on the line, but still needs to be followed by a newline.

In UNIX, the actual character to inform the terminal interface that you want to send EOF can be set with the stty command. If you execute stty -a, you'll see something like:

speed 38400 baud; rows 45; columns 150; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D;
eol = <undef>; eol2 = <undef>; swtch = ^Z; start = ^Q;
stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0; -parenb -parodd cs8 -hupcl
-cstopb cread -clocal -crtscts -ignbrk brkint -ignpar -parmrk
-inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany
-imaxbel opost -olcuc -ocrnl onlcr -onocr -onlret -ofill
-ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo
-echoe -echok -echonl -noflsh -tostop -echoctl -echoke

You can see at the end of the second line that eof is set to ^D (CTRLd). You can change this with:

stty eof ^x

to set it to CTRLx, for example. You can also set a huge number of other things, most of which will make your current terminal unusable, so be careful :-)

Bottom line, if you want to signal your program that the file is finished, use CTRLd for UNIX (or check stty if that doesn't work) or CTRLz for Windows. If you want to just get a line of input, use the \n character in your code as follows:

#include <stdio.h>
int main (void) {
    long nc = 0;
    while(getchar() != '\n')
        ++nc;
    printf("%ld\n", nc);
    return 0;
}

How are you ending your input and what system are you on?

If you are hitting an 'interrupt' or 'kill' control key combination then it's likely that you are killing your process before it can print.

If you use something like Ctrl-D on unix or Ctrl-Z at the start of a line on windows then this will signal 'end of input' without killing the process.

You can also try redirecting your input from a test file. e.g.:

myprogram <input.txt

On Windows either a CTRL-Z or F6 will signal the end of a file.


"Press enter"? The cycle in your code continues to iterate until it reaches the end-of-file marker. "Pressing enter" will not result in EOF. If you want to simulate EOF from the keyboard, consult the documentation for your terminal. In Windows, for example, you'd have to hit Ctrl+Z to generate EOF.