unix文件缺少EOF

时间:2012-09-13 05:32:42

标签: c unix

  

可能重复:
  fgetc does not identify EOF
  fgetc, checking EOF

我创建了一个文件并在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; 
}

如果我明确地给出 CTRL + D ,即使我使用char c,也会检测到EOF。

4 个答案:

答案 0 :(得分:4)

如果c的类型为char(并且char在编译器中未签名,则可能会发生这种情况,您可以通过检查CHAR_MIN的值来检查这一点)而不是int

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

因此,隐式地将EOF强制转换为unsigned char将失去EOF的真实值,并且比较将始终失败。

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

答案 1 :(得分:3)

缺少括号。应该是:

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

答案 2 :(得分:1)

请记住:fgetc()会返回int,而不是char。它必须返回int,因为它的返回值集包括所有可能的有效字符加上单独的(负)EOF指示符。

如果您对char使用c类型而不是int,则有两种可能的陷阱:

  1. 如果使用编译器对char类型进行了签名,则会将有效字符检测为EOF。通常,字符ÿ(y-umlaut,在Unicode中正式称为LATIN LOWER CASE Y WITH DIAERESIS,U + 00FF,ISO 8859-1中的十六进制代码0xFF,也称为Latin 1代码集)将被检测为等效于EOF,这是一个有效的角色。

  2. 如果类型char未签名,则比较永远不会成立。

  3. 这两个问题都很严重,使用正确的类型可以避免这两个问题:

    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和伪电传 - 设备)。

答案 3 :(得分:0)

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