1

I'm learning the C programming on a raspberry pi, however I found that my program never catches the EOF successfully. I use char c=0; printf("%d",c-1); to test the char type, finding that the char type ranges from 0 to 255, as an unsigned short. but the EOF defined in stdio.h is (-1). So is the wrong cc package installed on my Pi? how can I fix it? If I changed the EOF value in stdio.h manually, will there be further problems?


what worries me is that ,when I learning from the K&R book, there are examples which use code like while ((c=getchar())!=EOF), I followed that on my Ubuntu machine and it works fine. I just wonder if such kind of syntax is abandoned by modern C practice or there is something conflict in my Raspberry Pi?

here is my code:

#include <stdio.h>
int main( void )
{
        char c;
        int i=0;
        while ((c=getchar())!=EOF&&i<50) {
                putchar(c);
                i++;
        }
        if (c==EOF)
                printf("\nEOF got.\n");
        while ((c=getchar())!=EOF&&i<500) {
                printf("%d",c);
                i++;
        }
}

even when I redirect the input to an file, it keeps printing 255 on the screen, never terminate this program.


Finally I found that I'm wrong,In the K&R book, it defined c as an int, not a char. Problem solved.

social_loser
  • 143
  • 1
  • 6
  • 3
    The code `char c=0; printf("%d",c--);` prints `0` because `c` is decremented **after** its value is used in `printf()`. This code doesn't prove anything. Take a look at some [documentation](http://en.cppreference.com/w/c/language/operator_incdec). – axiac Nov 11 '15 at 14:44
  • Post the code that "never catches the EOF successfully" rather than test code. – chux - Reinstate Monica Nov 11 '15 at 14:54
  • to axiac : I changed `c--` to `c-1` in my post. – social_loser Nov 11 '15 at 15:01
  • you have many wrong assumptions: `char` can represent -1 if it's a signed type (which is the most common configuration). See [Is char signed or unsigned by default?](https://stackoverflow.com/q/2054939/995714). And EOF can be any negative values. See [Is EOF always negative?](https://stackoverflow.com/q/1624051/995714), [why in c language EOF IS -1?](https://stackoverflow.com/q/4569066/995714) – phuclv Apr 27 '19 at 04:49

4 Answers4

5

You need to store the character read by fgetc(), getchar(), etc. in an int so you can catch the EOF. This is well-known and has always been the case everywhere. EOF must be distinguishable from all proper characters, so it was decided that functions like fgetc() return valid characters as non-negative values (even if char is signed). An end-of-file condition is signalled by -1, which is negative and thus cannot collide with any valid character fgetc() could return.

Do not edit the system headers and especially do not change the value of constants defined there. If you do that, you break these headers. Notice that even if you change the value of EOF in the headers, this won't change the value functions like fgetc() return on end-of-file or error, it just makes EOF have the wrong value.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • Furthermore, it's probably for the best to check `feof()` and `ferror()` after any read/write operation that returned unexpected values (like `EOF`). –  Nov 11 '15 at 14:43
  • @Rhymoid Checking for one of them is sufficient as `feof()` and `ferror()` cannot be raised at the same time as far as I know. Also, the error flag persists until it is cleared with `clearerr()`, an idiom is to continue reading the remainder of the data and then at the end checking the flags as to save a lot of error handling code. – fuz Nov 11 '15 at 14:46
  • @chux Your remark is correct, but all actual characters are returned as positive values from `fgetc()` so a distinction can be made. I'm going to edit my answer to incorporate this. – fuz Nov 11 '15 at 14:47
  • @chux Better this way? – fuz Nov 11 '15 at 14:51
2

Why is EOF defined to be −1 when −1 cannot be represented in a char?

Because EOF isn't a character but a state.

alk
  • 69,737
  • 10
  • 105
  • 255
2

If I changed the EOF value in stdio.h manually, will there be further problems?

Absolutely, since you would be effectively breaking the header entirely. A header is not an actual function, just a set of prototypes and declarations for functions that are defined elsewhere ABSOLUTELY DO NOT change system headers, you will never succeed in doing anything but breaking your code, project and/or worse things.

On the subject of EOF: EOF is not a character, and thus cannot be represented in a character variable. To get around this, most programmers simple use an int value (by default signed) that can interpret the -1 from EOF. The reason that EOF can never be a character is because otherwise there would be one character indistinguishable from the end of file indicator.

Magisch
  • 7,312
  • 9
  • 36
  • 52
1

int versus char.

fgetc() returns an int, not char. The values returned are in the range of unsigned char and EOF. This is typically 257 different values. So saving the result in char, signed char, unsigned char will lose some distinguishably.

Instead save the fgetc() return value in an int. After testing for an EOF result, the value can be saved as a char if needed.

// char c;
int c;
...
while ((c=getchar())!=EOF&&i<50) {
  char ch = c;
  ...

Detail: "Why is EOF defined to be −1 when −1 cannot be represented in a char?" misleads. On systems where char is signed and EOF == -1, a char can have the value of EOF. Yet on such systems, a char can have a value of -1 that represents a character too - they overlap. So a char cannot distinctively represent all char and EOF. Best to use an int to save the return value of fgetc().

... the fgetc function obtains that character as an unsigned char converted to an int and ...
If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, ... and the fgetc function returns EOF. ... C11 §7.21.7.1 2-3

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256