Search code examples
ceofgetchar

getchar() doesn't pass EOF and Ctrl+Z doesn't terminate the program on Cygwin


Here is a simple program, counting strings, symbols and words.

Everything is ok with the computation, using Cygwin.

But while launching, after input values, the program doesn't print nc, nw, nl and wait for entering further values.

Changing EOF to 13 (Enter) doesn't help anyway.

ctrl+Z is useful too: the program is stopping, writing [n]+ Stopped, where 'n' is always different number.

The code is

#include <stdio.h>
#define IN 1
#define OUT 0


int main () {

    char c;
    int state;
    int nc, nw, nl;
    state = OUT;    

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

        if (c == 'n') 
            nw++;


        if (c == '\n' || c == ' ' || c == '\t') 
            state = OUT;
        else if (state = OUT){
            state = IN;
            nw++;
        }

    }
    printf ("%d %d %d", nc, nl, nw);
}

Solution

  • getchar returns int, not char. It has to do this because it can either return a character value or return the special value EOF to indicate the end of the input file. Since EOF has to be different from all values of the char type, it does not have the type char. So you need to define the variable that contains its return value as an int, not as char.

    On some platforms, the char type is signed, and the getchar function does not in fact return the character value, but the character value wrapped around to a non-negative value. In practice, what this means is that ASCII characters are unchanged but, on some platforms, non-ASCII characters are transformed to a value between 128 and 255 instead of between -128 and -1. So in general you need to cast the return value of getchar to an char when you use it as a character. On platforms where the char type is unsigned, this doesn't change anything, but on platforms where the char type is signed, it is necessary to avoid character 255 being mistaken as the end of the file.

    int c;
    …
    while ((c = getchar()) != EOF) {
        …
        if (c == 'n') /* ok because 'n' is part of ASCII and thus always positive */
            …
        if ((char)c == some_other_char) /*cast needed in general*/
            …
    }
    

    In Cygwin, like in other Unix-like systems, press Ctrl+D at the beginning of a line to signal the end of the input. Under Windows, you need to press Ctrl+Z (under Cygwin, again like in other Unix-like systems, that instead suspends the programs: it's stopped, but can be resumed with the command bg). Neither of these send a control character to the program, they send an end-of-file indication which C's getchar implementation translates to the EOF value.