fgetc返回一个未知字符

fgetc返回一个未知字符,c,stdio,C,Stdio,我有以下代码: FILE *f = fopen('/path/to/some/file', 'rb'); char c; while((c = fgetc(f)) != EOF) { printf("next char: '%c', '%d'", c, c); } 出于某种原因,当打印出字符时,在文件末尾,将打印出一个不可渲染的字符以及ASCII序号-1 next char: '?', '-1' 这应该是什么角色?我知道这不是EOF,因为有一个检查,在打印字符后,程序很快就会出错。这

我有以下代码:

FILE *f = fopen('/path/to/some/file', 'rb');
char c;
while((c = fgetc(f)) != EOF)
{
    printf("next char: '%c', '%d'", c, c);
}
出于某种原因,当打印出字符时,在文件末尾,将打印出一个不可渲染的字符以及ASCII序号-1

next char: '?', '-1'
这应该是什么角色?我知道这不是EOF,因为有一个检查,在打印字符后,程序很快就会出错。

这就是罪魁祸首:

char c;
请将其更改为:

int c;

fgetc
的返回类型是
int
,而不是
char
。在某些平台上,将
int
转换为
char
时会出现奇怪的行为。

问题在于
fgetc()
及其相关函数返回的是
int
,而不是
char

如果未设置流指向的输入流的文件结束指示符,并且 下一个字符出现时,
fgetc
函数将该字符作为
无符号字符
转换为
int
,并前进该字符的相关文件位置指示器 流(如果定义)

如果设置了流的文件结束指示符,或者流位于文件结束处,则- 设置流的文件指示符,并且
fgetc
函数返回
EOF

它必须返回每个可能的有效字符值和一个不同的值,
EOF
(它是负数,通常但不一定是
-1

当您将值读入
char
而不是
int
时,会发生以下两种情况之一:

  • 如果plain
    char
    是无符号的,则永远不会得到等于EOF的值,因此循环永远不会终止

  • 如果明文
    char
    被签名,那么您可能会将合法字符0xFF(通常是ÿ,y-umlaut,U+00FF,拉丁文小写字母y加上DIAERESIS)视为与EOF相同,因此您会过早地检测到EOF

不管怎样,这都不好

修复 修复方法是使用
intc而不是
字符c


顺便提一下,
fopen()
调用不应编译:

FILE *f = fopen('/path/to/some/file', 'rb');
应该是:

FILE *f = fopen("/path/to/some/file", "rb");

始终检查
fopen()
的结果;在所有的I/O函数中,它几乎比任何其他函数都更容易发生故障(不是因为它本身的故障,而是因为用户或程序员在文件名上犯了错误)。

FYI:您应该确保
fopen
不返回NULL,表示失败。这可能是我所做的或其他十几个类似答案的重复,更不用说其他人在同一主题上所做的回答了。我假设发生的情况是,因为与其他数据类型不同,
char
有时是无符号的,-1(常见的
EOF
值)隐式转换为255。当再次转换为
int
以与
EOF
进行比较时,它保持255,因此不等于-1。成功完成后,fopen()返回一个文件指针。否则,将返回NULL并设置errno以指示错误。在fopen中检查错误时使用以下命令:if((fp=fopen(“mat”、“rb”))==NULL){printf(“无法打开文件。\n”);返回0;}