0

可能重复:
fgetc 无法识别 EOF
fgetc,检查 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.

4

4 回答 4

4

如果cis的类型char(并且char在您的编译器中是无符号的,您可以通过检查 in 的值来检查CHAR_MIN)而不是 not ,就会发生这种情况int

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

因此,隐式转换EOFunsigned char将失去真正的价值,EOF并且比较总是会失败。

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

于 2012-09-13T05:42:58.743 回答
3

缺少括号。应该:

while((c = fgetc(fp)) != EOF)
于 2012-09-13T05:41:15.023 回答
1

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

char如果您使用 type forc而不是 ,则有两个可能的陷阱int

  1. 如果该类型char是用您的编译器签名的,您将检测到一个有效字符作为 EOF。通常,字符 ÿ(y-umlaut,在 Unicode 中正式称为 LATIN LOWER CASE Y WITH DIAERESIS,U+00FF,在 ISO 8859-1 aka Latin 1 代码集中的十六进制代码 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.

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


与 CP/M 和 DOS 不同,Unix 不使用任何字符来表示 EOF;当没有更多字符要读取时,您会到达 EOF。让很多人感到困惑的是,如果你在终端输入某个组合键,程序就会检测到 EOF。实际发生的是终端驱动程序识别字符并将任何未读字符发送到程序。如果没有未读字符,则程序返回 0 个字节,这与到达文件末尾时得到的结果相同。因此,字符组合(通常,但不总是,Ctrl-D)似乎向程序“发送 EOF”。但是,如果您使用的是字符,则字符不会存储在文件中cat >file; 此外,如果您读取包含 control-D 的文件,那是一个字节值为 0x04 的完美字符。如果一个程序生成一个 control-D 并将其发送给一个程序,这并不表示该程序的 EOF。它是 Unix 终端(tty 和 pty — 电传打字机和伪电传打字机 — 设备)的严格属性。

于 2012-09-13T05:55:03.130 回答
0

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

于 2012-09-13T05:35:14.880 回答