问题
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.
回答1:
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.
回答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.
回答3:
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.
回答4:
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 anint
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 returnsEOF
. ... C11 §7.21.7.1 2-3
来源:https://stackoverflow.com/questions/33652499/why-is-eof-defined-to-be-%e2%88%921-when-%e2%88%921-cannot-be-represented-in-a-char