C中的不同输出内容文件副本
您好,我有一个简单的复制文件程序在C中,但我不能解释为什么我得到不同的输出在目标文件时,我使用第二种方法。 具有for循环的正确输出:C中的不同输出内容文件副本,c,file-copying,fgetc,getc,C,File Copying,Fgetc,Getc,您好,我有一个简单的复制文件程序在C中,但我不能解释为什么我得到不同的输出在目标文件时,我使用第二种方法。 具有for循环的正确输出: I am the worst programmer in the world! :D And this is bla bla bla bla more bla bla bla... 但在while循环中,会在EOF中生成一个随机字符: I am the worst programmer in the world! :D And this is bla b
I am the worst programmer in the world!
:D
And this is bla bla bla bla
more bla bla bla...
但在while循环中,会在EOF中生成一个随机字符:
I am the worst programmer in the world!
:D
And this is bla bla bla bla
more bla bla bla...
代码是
int main()
{
int i;
char ch;
create_files();
FILE *src = fopen("best.txt", "r");
FILE *dst = fopen("copied.txt", "w");
for(i=getc(src); i!=EOF; i=getc(src)) //correct copy
{
putc(i, dst);
}
/* while(!feof(src)) //woot?
{
ch=fgetc(src);
fputc(ch,dst);
}*/
fclose(dst);
fclose(src);
return 0;
}
void create_files()
{
FILE *fp;
fp = fopen("best.txt","w");
fprintf(fp,"I am the worst programmer in the world!\n:D\n And this is bla bla bla bla\n more bla bla bla...\n");
fclose(fp);
}
我使用了fputc或putc和fgetc或getc,但仍然是一样的。我忘了什么吗?编辑
看起来这不是真正的问题,但我会保留答案作为建议
我唯一注意到的是:
char ch;
根据您的系统,char
可以是有符号的,也可以是无符号的,足以容纳EOF,或者不够。您的while
循环可能表明您的操作系统适合后一种情况
改为使用
int
并尝试一下。您的while
循环有一个off by one错误。它读/写一个额外的字符,这就是奖金代码>来自-您将fgetc()
返回的EOF值写入了输出文件 第一个循环获取字符(可能检测到EOF),然后检查未检测到EOF的值,并可能执行写入字符的块(直到读取所有字符)
第二个循环检查是否检测到EOF,获取字符(可能检测到EOF),写入字符(不考虑可能是什么),并可能继续下一个字符(如果未检测到EOF)
在第二个循环中,在检查字符是否为EOF之前写入该字符。while循环会给您一个随机字符,因为在读取失败之前,EOF实际上不会被标记。因此,while循环中发生的事情是,执行读取操作,fgetc
失败,设置EOF,并返回一个duff值,然后打印
构造while循环的更好方法是:
ch=fgetc(src);
while (!feof(src)) {
fputc(ch,dst);
ch=fgetc(src);
}
什么
是的,是:
检查EOF
读取一个字符,可能导致EOF
输出刚刚读取的字符,不检查EOF
当EOF发生时,(3)仍在下一次迭代中签入(1)之前执行。特殊值EOF
转换为char
并输出
正确的循环是
while ((ch = fgetc(src)) != EOF)
fputc(ch, dst);
假设ch
给出类型int
,因为char
不能表示EOF
。注意支票内的分配;有些程序员会告诉你这很难看,但是很多人都在使用它,你可能会习惯它。用于
循环的变量也是正确的
(1除外:fputc
相当于putc
和fgetc
到getc
,只要您不尝试在函数指针上下文中使用它们。)
(旁白2:您的while
循环也不会检查流错误,而检查EOF
也会返回捕捉到的内容。)不会做您认为它会做的事情。阅读文档。它不测试下一次读取是否会尝试读取超过文件结尾的内容;它检查上次失败的读取尝试是否失败,因为已经到达文件末尾。@pmg是正确的feof
应在循环后使用,以检查是否发生EOF而不是错误。谢谢。我认为(!feof(src)与((ch=fgetc(src))相同!=EOF)@GeoPapas:否。您必须在读取和写入之间进行检查,然后还必须检查ferror
。如果我想在第一次复制后重新复制文件,则必须使用ungetc?@GeoPapas:否。您应该fseek
到文件的开头。ungetc
只保证可以推送一个字符k、 它用于在标记器中实现预读。
while ((ch = fgetc(src)) != EOF)
fputc(ch, dst);