记住:fgetc()
返回一个int
,而不是一个char
。它必须返回一个,int
因为它的一组返回值包括所有可能的有效字符以及一个单独的(负)EOF 指示符。
char
如果您使用 type forc
而不是 ,则有两个可能的陷阱int
:
如果该类型char
是用您的编译器签名的,您将检测到一个有效字符作为 EOF。通常,字符 ÿ(y-umlaut,在 Unicode 中正式称为 LATIN LOWER CASE Y WITH DIAERESIS,U+00FF,在 ISO 8859-1 aka Latin 1 代码集中的十六进制代码 0xFF)将被检测为等同于 EOF,当它是一个有效的字符。
如果类型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 — 电传打字机和伪电传打字机 — 设备)的严格属性。