【问题标题】:fgetc returns an unknown characterfgetc 返回一个未知字符
【发布时间】:2014-04-28 02:27:26
【问题描述】:

我有以下代码:

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,因为有一个检查,在字符打印后很快,程序 SEGFAULT。

【问题讨论】:

标签: c stdio


【解决方案1】:

问题在于fgetc() 及其亲属返回的是int,而不是char

如果 stream 指向的输入流的文件结束指示符没有设置并且 如果存在下一个字符,fgetc 函数将获得该字符作为转换为 intunsigned char 并推进相关的文件位置指示符 流(如果已定义)。

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

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

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

  • 如果普通的 char 是无符号的,那么你永远不会得到等于 EOF 的值,因此循环永远不会终止。

  • 如果普通 char 被签名,那么你可能会误认为一个合法字符,0xFF(通常是 ÿ、y-变音符号、U+00FF、带有分音符号的拉丁小写字母 Y)被视为与 EOF 相同,所以您过早地检测到 EOF。

不管怎样都不好。

修复

解决方法是使用int c; 而不是char c;


顺便说一句,fopen() 调用不应该编译:

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

应该是:

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

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

【讨论】:

  • 成功完成后 fopen() 返回一个 FILE 指针。否则,返回 NULL 并设置 errno 以指示错误。在 fopen 中使用以下错误检查: if((fp=fopen("mat", "rb"))==NULL) { printf("Cannot open file.\n");返回0; }
【解决方案2】:

这是罪魁祸首:

char c;

请改成:

int c;

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

【讨论】:

  • 我想发生的事情是因为 char 有时是无符号的,不像其他数据类型,-1(一个常见的 EOF 值)被隐式转换为 255。然后再次转换为 @ 987654330@ 与 EOF 比较,它保持 255,因此不等于 -1。
猜你喜欢
  • 2012-01-25
  • 1970-01-01
  • 2011-05-14
  • 2020-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-11
相关资源
最近更新 更多