2012-09-13 76 views
0

可能重复:
fgetc does not identify EOF
fgetc, checking EOFEOF缺少UNIX文件

我已经在Unix中创建的文件,并把它命名为 “file.txt的”。我试图从我的C程序中读取文件内容。我无法收到EOF字符。 Unix不会在创建文件时存储EOF字符?如果是的话是什么读取使用C.

这里从一个Unix创建的文件的EOF的另一种方法是代码示例

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; 
} 

如果我明确给出即使检测到EOF CTRL + d当我使用char c

+2

[fgetc无法识别EOF]的可能重复(http://stackoverflow.com/questions/3977223/fgetc-does-not-identify-eof),另请参阅http://stackoverflow.com/questions/11057259/fgetc-checking-eof以及其他很多 – Mat

+1

另请注意:EOF不是“存储在文件中”,它只是I/O函数告诉你它们到达文件结尾的一种方式。末尾没有存储魔术字节。 – Mat

+2

请注意它应该是'FILE * fp;'而不是'File * fp;',并且您还应该在通过变量'fp'读取任何内容之前检查文件是否已成功打开。 –

回答

4

可能发生这种情况如果c类型是char而不是int(和char是在你的编译器签名,你可以通过检查CHAR_MIN在值检查)。

根据C标准,EOF的值为负值。

因此,隐式铸造EOFunsigned char将失去真实值EOF并且比较总是失败。

UPDATE:有一个更大的问题必须先解决。在表达式c = fgetc(fp) != EOF中,首先评估fgetc(fp) != EOF(至0或1),然后将值分配给c。如果文件中至少有一个字符,则fgetc(fp) != EOF将评估为0,并且while循环的主体将永远不会执行。您需要添加括号,如下所示:(c = fgetc(fp)) != EOF

0

您不显示如何声明变量c它应该是int类型,而不是char

3

缺少括号。应该是:

while((c = fgetc(fp)) != EOF) 
+0

:)不幸的是,这不.. –

+0

这可以防止代码编译 - 但不解释运行时错误。它还告诉我们,问题中的代码不是编译的代码,这总是会使调试更加困难。 –

+0

这将如何防止代码编译?将不等式运算符的结果值赋给标量变量是完全有效的C. –

1

记住:fgetc()返回int,而不是char。它必须返回一个int,因为它的一组返回值包含所有可能的有效字符和一个单独的(负)EOF指示符。

有两种可能的陷阱,如果你使用类型为charc代替int

  1. 如果类型char与您签订的编译器,你会发现一个有效的字符为EOF。通常,在ISO 8859-1(又名拉丁语1代码集)中,字符ÿ(y-umlaut,在Unicode中被正式称为LATIN LOWER CASE Y WITH DIAERESIS,U + 00FF,十六进制代码0xFF)将被检测为等同于EOF,这是一个有效的角色。

  2. 如果类型char是无符号的,那么比较永远不会是真的。

这两个问题是严重的,无一不是通过使用正确的类型回避:

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); 
} 

注意该类型是FILE而不是File。请注意,在尝试通过fp阅读之前,您应该检查文件是否已打开。


如果我明确给予CTRL + d,当我使用char c即使检测到EOF。

这意味着您的编译器为您提供了char作为签名类型。这也意味着您将无法在包含ÿ的文件中准确地计算行数。


与CP/M和DOS不同,Unix不使用任何字符来表示EOF;当没有更多字符可读时,您到达EOF。令许多人感到困惑的是,如果您在终端键入某个组合键,程序会检测到EOF。实际发生的事情是,终端驱动程序识别该字符并将任何未读字符发送到该程序。如果没有未读字符,程序会返回0字节,这与您到达文件结尾时的结果相同。因此,字符组合(通常,但并非总是,Ctrl-D)似乎将'EOF'发送给程序。但是,如果您使用的是cat >file,则不会将该字符存储在文件中;此外,如果您读取包含control-D的文件,则该文件是字符值为0x04的完美字符。如果一个程序生成一个control-D并将它发送给一个程序,那么这并不表示程序的EOF。它完全是Unix终端的一种属性(tty和pty - teletype和pseudo-teletype - devices)。