我想将二进制文件源复制到文件目标.而已!该代码的灵感来自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;
}
Run Code Online (Sandbox Code Playgroud)
结果文件大小不同.
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
Run Code Online (Sandbox Code Playgroud)
好的,那有什么问题呢?
我知道char是未签名的,并且在80以上时签名.请看这里.
这在我使用时得到证实,printf("%x\n", ch);
它有时会返回大约50%的时间FFFFFFE1
.
我的问题的解决方案是使用int
iso char
.
我不使用花哨的编译器选项.
为什么几乎所有代码示例都发现将fgetc()返回到char
iso a int
,哪个更正确?
我错过了什么?
ISO C强制要求fgetc()
返回,int
因为除了文件结束指示符之外,它必须能够返回每个可能的字符.
这样会将返回值转换成代码char
,并使用它来检测EOF,一般是完全错误的,不应该被使用.
话虽如此,你提供的两个例子实际上并没有这样做.
其中一个使用fseek
和ftell
获取文件中的字节数,然后使用它来控制读/写循环.这可能会有问题,因为文件在检索到大小后实际上可以改变大小,但是尝试强制int
进入文件时这是一个不同的问题char
.
另一个feof
在读取字符后立即使用,以检查是否已到达文件末尾.
但你是对的,最简单的方法就是简单地正确使用返回值,例如:
int charInt;
while ((charInt = fgetc(inputHandle)) != EOF)
doSomethingWith(charInt);
Run Code Online (Sandbox Code Playgroud)
问题是你当时看到的大部分代码都是错误的。有 3 种类型char
-signed
和unsigned
普通字符。现在,如果默认情况下普通 char 有符号,则具有十进制值的字符255
将被视为等于-1
(EOF)。这不是你想要的。(是的,十进制值255
不能用有符号字符表示,但它是实现定义的行为,并且在大多数情况下,它将0xFF
在 中存储位模式char
)。
其次,如果char
是unsigned
那么它将EOF
被认为是0xFF
现在也是错误的并且比较将失败。(知道EOF
is-1
它将被转换为CHAR_MAX
which is255
或0xFF
)。
这就是为什么int
要考虑它可以正确保存 的值EOF
,这就是您应该如何使用它。