我想将二进制文件源复制到文件目标。而已!该代码的灵感来自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 2,example 3 example 4,int
,...
在example a找到的例子:char
,...
我不使用花哨的编译器选项。
为什么几乎所有的代码示例都将fgetc()返回到int
i.s.o.一个fgetc()
,哪个会更正确?
我错过了什么?
ISO C要求int
返回char
,因为除了文件结束指示符之外,它必须能够返回每个可能的字符。
因此,将返回值放入fseek
并使用它来检测EOF的代码通常是完全错误的,不应该使用。
话虽如此,你提供的两个例子实际上并没有这样做。
其中一个使用ftell
和int
来获取文件中的字节数,然后使用它来控制读/写循环。这可能会有问题,因为文件在检索到大小后实际上可以改变大小但是尝试将char
强制转换为feof
则是另一个问题。
另一个在读取字符后立即使用int charInt;
while ((charInt = fgetc(inputHandle)) != EOF)
doSomethingWith(charInt);
来检查是否已到达文件末尾。
但你是对的,最简单的方法就是简单地正确使用返回值,例如:
char
那么事情是你看到的大多数代码然后是错误的。有三种类型的signed
- unsigned
,255
和plain char。现在,如果默认情况下将普通字符签名,则具有十进制值-1
的字符将被视为等于255
(EOF)。这不是你想要的。 (是十进制值0xFF
将无法在签名字符中表示,但它是实现定义的行为,并且在大多数情况下,它将在char
中存储位模式char
)。
其次,如果unsigned
是EOF
那么它0xFF
将被视为EOF
现在也是错误的,比较将失败。 (知道-1
是CHAR_MAX
它将被转换为255
,即0xFF
或int
)。
这就是为什么EOF
被认为是正确保持qazxswpoi值的原因,这就是你应该如何使用它。