0

Possible Duplicate:
fgetc does not identify EOF
fgetc, checking EOF

I have created a file and named it "file.txt" in Unix. I tried to read the file content from my C program. I am not able to receive the EOF character. Unix doesn't store EOF character on file creation? If so what is the alternative way to read the EOF from a Unix created file using C.

Here's the code sample

int main(){
File *fp;
int nl,c;
nl =0;
fp = fopen("file.txt", "r");
while((c = fgetc(fp)) != EOF){
  if (c=='\n')
    nl++;
}
return 0; 
}

If I explicitly give CTRL + D the EOF is detected even when I use char c.

Community
  • 1
  • 1
Access Denied
  • 224
  • 1
  • 14
  • 2
    possible duplicate of [fgetc does not identify EOF](http://stackoverflow.com/questions/3977223/fgetc-does-not-identify-eof), see also http://stackoverflow.com/questions/11057259/fgetc-checking-eof and many, many others – Mat Sep 13 '12 at 05:35
  • 1
    Also note: EOF is not "stored in files", it's just a way for I/O functions to tell you they reached the end of a file. There isn't a magic byte stored at the end. – Mat Sep 13 '12 at 05:37
  • 2
    Note that it should be `FILE *fp;` and not `File *fp;`, and you should also check that the file was opened successfully before reading anything via the variable `fp`. – Jonathan Leffler Sep 13 '12 at 05:55

4 Answers4

4

This can happen if the type of c is char (and char is unsigned in your compiler, you can check this by examining the value of CHAR_MIN in ) and not int.

The value of EOF is negative according to the C standard.

So, implicitly casting EOF to unsigned char will lose the true value of EOF and the comparison will always fail.

UPDATE: There's a bigger problem that has to be addressed first. In the expression c = fgetc(fp) != EOF, fgetc(fp) != EOF is evaluated first (to 0 or 1) and then the value is assigned to c. If there's at least one character in the file, fgetc(fp) != EOF will evaluate to 0 and the body of the while loop will never execute. You need to add parentheses, like so: (c = fgetc(fp)) != EOF.

Alexey Frunze
  • 61,140
  • 12
  • 83
  • 180
3

Missing parentheses. Should be:

while((c = fgetc(fp)) != EOF)
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • This prevents the code compiling - but doesn't explain a run-time error. It also tells us that the code in the question is not the code that was compiled, which always makes the debugging harder. – Jonathan Leffler Sep 13 '12 at 05:48
  • How would that prevent the code from compiling? Assigning the value of the result of the inequality operator to a scalar variable is perfectly valid C. – R.. GitHub STOP HELPING ICE Sep 13 '12 at 11:59
1

Remember: fgetc() returns an int, not a char. It has to return an int because its set of return values includes all possible valid characters plus a separate (negative) EOF indicator.

There are two possible traps if you use type char for c instead of int:

  1. If the type char is signed with your compiler, you will detect a valid character as EOF. Often, the character ÿ (y-umlaut, officially known in Unicode as LATIN LOWER CASE Y WITH DIAERESIS, U+00FF, hex code 0xFF in the ISO 8859-1 aka Latin 1 code set) will be detected as equivalent to EOF, when it is a valid character.

  2. If the type char is unsigned, then the comparison will never be true.

Both problems are serious, and both are avoided by using the correct type:

FILE *fp = fopen("file.txt", "r");
if (fp != 0)
{
    int c;
    int nl = 0;
    while ((c = fgetc(fp)) != EOF)
        if (c == '\n')
            nl++;
    printf("Number of lines: %d\n", nl);
}

Note that the type is FILE and not File. Note that you should check that the file was opened before trying to read via fp.


If I explicitly give CTRL + D, the EOF is detected even when I use char c.

This means that your compiler provides you with char as a signed type. It also means you will not be able to count lines accurately in files which contain ÿ.


Unlike CP/M and DOS, Unix does not use any character to indicate EOF; you reach EOF when there are no more characters to read. What confuses many people is that if you type a certain key combination at the terminal, programs detect EOF. What actually happens is that the terminal driver recognizes the character and sends any unread characters to the program. If there are no unread characters, the program gets 0 bytes returned, which is the same result you get when you've reached the end of file. So, the character combination (often, but not always, Ctrl-D) appears to 'send EOF' to the program. However, the character is not stored in a file if you are using cat >file; further, if you read a file which contains a control-D, that is a perfectly fine character with byte value 0x04. If a program generates a control-D and sends that to a program, that does not indicate EOF to the program. It is strictly a property of Unix terminals (tty and pty — teletype and pseudo-teletype — devices).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

You do not show how you declare the variable c it should be of type int, not char.

heijp06
  • 11,558
  • 1
  • 40
  • 60