我写了一个代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
fp=fopen("lets.txt","r+");
if(fp==NULL)
{
printf("ERROR");
exit(1);
}
else
{
char ch,ch1;
while(!feof(fp))
{
ch= fgetc(fp);
printf("%c",ch);
}
printf("\n\nYou want to write something? (1/0)");
int n;
scanf("%d",&n);
if(n==1)
{
fputs("Jenny",fp);
ch1 = fgetc(fp);
printf("%c\n", ch1);
while(ch1 != EOF)
{
ch1=fgetc(fp);
printf("%c",ch1);
}
fclose(fp);
}
else{
printf("File Closed ");
fclose(fp);
}
}
}
我尝试在已经存在的文件“lets.txt”
中插入字符串
但当我运行这段代码时,它显示在终端
中
我本来以为这只是把Jenny放进最终文件,但它也添加了其他文本,这些文本在它之前就存在,还有很多NULL。这是因为临时内存存储之类的原因,还是只是代码中的一些错误?
3条答案
按热度按时间oxiaedzo1#
首先,这些线条
都是错的。
如果你想保证
ch
能够表示值EOF
,并且还想能够将它与每个可能的字符代码区分开,那么你必须将fgetc
的返回值存储在int
中,而不是char
中。不是char
。有关此问题的详细信息,请参阅this other answer。此外,函数
feof
将仅返回非零值(即true),如果上一个读取操作已经由于文件结束而失败。它不提供下一个读取操作是否会失败的任何指示。这意味着如果fgetc
返回EOF
,则将打印该值,就像fgetc
成功一样,这是错误的。有关此问题的详细信息,请参见以下问题:Why is “while( !feof(file) )” always wrong?
鉴于上述原因,我建议你将这些行改为:
另一个问题是,当文件以更新模式打开时(即模式字符串中包含
+
,例如"r+"
),你不能自由地在读和写之间切换。根据ISO C11标准§ 7.21.5.3 ¶ 7,fflush
函数或文件定位函数(fseek
、fsetpos
或rewind
)的调用,以及如果您违反了这些规则中的任何一条,那么您的程序将调用undefined behavior,这意味着任何事情都可能发生,包括您可能得到无效输出。
因此,我建议你把台词改一下
致:
与
fflush( fp );
这一行相比,fseek( fp, 0, SEEK_CUR );
这一行是绝对必要的,而根据上面提到的规则,实际上并不必要,因为你遇到了文件尾,但是无论如何保留这一行可能是一个好主意,例如,如果你后来改变你的程序,因为除了文件尾之外的其他原因而停止读取,在这种情况下,这一行是必需的。zxlwwiss2#
Re:"我把while循环的条件改成了这个简单的形式-ch = fgetc(fp);while(ch!= EOF)但它仍然显示相同的结果。
getchar()
返回的值必须存储在int
:**中ch
已声明为char
。将值存储在char
中会使EOF
测试不可靠。C17声明EOF
具有负int值。在某些实现中,char
为unsigned
,因此它不能表示负值。在类型
char
有符号的实现中,假定EOF
定义为-1
(这是大多数实现的情况),不可能将EOF
与字符代码255
区分开来(字符代码255
在char
中存储为值-1
,而在int
中存储为255
)。在手册页中:
fgec()、gec()和getchar()返回读取的字符,作为无符号字符转换为***int***或文件结束时的EOF或错误。
它还指出:
如果getchar()返回的整数值存储到char类型的变量中,然后与整数常量EOF进行比较,则比较可能永远不会成功,因为扩展为整数的char类型变量的符号扩展是由实现定义的。
其也与
fgetc
相关。将
ch
声明为int
。cgvd09ve3#
在读写之间切换时没有设置文件指针。MSVC man page表示大约
fopen
但是,当从阅读切换到写时,输入操作必须遇到
EOF
标记。如果没有EOF
,则必须使用对文件定位函数的干预调用。文件定位函数是fsetpos
、fseek
和rewind
。当从写切换到读时,你必须使用一个介入调用到fflush
或到一个文件定位函数.