为什么将fgetc()返回给char i.s.o.诠释?

问题描述 投票:1回答:2

我想将二进制文件源复制到文件目标。而已!该代码的灵感来自Internet上的许多示例。

#include <stdio.h>

int main(int argc, char **argv) {

    FILE *fp1, *fp2;
    char ch;

    fp1 = fopen("source.pdf", "r");
    fp2 = fopen("target.pdf", "w");

    while((ch = fgetc(fp1)) != EOF)
        fputc(ch, fp2);

    fclose(fp1);
    fclose(fp2);

    return 0;

}

结果文件大小不同。

root@vm:/home/coder/test# ls -l
-rwxr-x--- 1 root root 14593 Feb 28 10:24 source.pdf
-rw-r--r-- 1 root root   159 Mar  1 20:19 target.pdf

好的,那有什么问题?

我知道char是未签名的,并且在80以上时签名。请参阅here

这是在我使用printf("%x\n", ch);时确认的,FFFFFFE1大约有50%的时间返回有时像int

我的问题的解决方案是使用char i.s.o. char

example 1找到的例子:example 2example 3 example 4int,...

example a找到的例子:char,...

我不使用花哨的编译器选项。

为什么几乎所有的代码示例都将fgetc()返回到int i.s.o.一个fgetc(),哪个会更正确?

我错过了什么?

c variables fgetc
2个回答
5
投票

ISO C要求int返回char,因为除了文件结束指示符之外,它必须能够返回每个可能的字符。

因此,将返回值放入fseek并使用它来检测EOF的代码通常是完全错误的,不应该使用。


话虽如此,你提供的两个例子实际上并没有这样做。

其中一个使用ftellint来获取文件中的字节数,然后使用它来控制读/写循环。这可能会有问题,因为文件在检索到大小后实际上可以改变大小但是尝试将char强制转换为feof则是另一个问题。

另一个在读取字符后立即使用int charInt; while ((charInt = fgetc(inputHandle)) != EOF) doSomethingWith(charInt); 来检查是否已到达文件末尾。


但你是对的,最简单的方法就是简单地正确使用返回值,例如:

char

3
投票

那么事情是你看到的大多数代码然后是错误的。有三种类型的signed - unsigned255和plain char。现在,如果默认情况下将普通字符签名,则具有十进制值-1的字符将被视为等于255(EOF)。这不是你想要的。 (是十进制值0xFF将无法在签名字符中表示,但它是实现定义的行为,并且在大多数情况下,它将在char中存储位模式char)。

其次,如果unsignedEOF那么它0xFF将被视为EOF现在也是错误的,比较将失败。 (知道-1CHAR_MAX它将被转换为255,即0xFFint)。

这就是为什么EOF被认为是正确保持qazxswpoi值的原因,这就是你应该如何使用它。

© www.soinside.com 2019 - 2024. All rights reserved.