关于fgetc与feof工作机制及文件追加代码异常的技术咨询
为什么先检查feof会写出多余的0xFF?聊聊fgetc和feof的真实机制
嘿,这个坑我当年刚学C文件操作的时候也踩过!咱们一步一步把这个问题拆明白:
先搞懂fgetc和feof到底是干啥的
- fgetc:它的核心是「尝试读一个字符」。成功的话,会返回这个字符的无符号ASCII值(转成int类型,范围0-255);如果已经读到文件末尾,或者读操作出错,就返回
EOF(通常是-1,二进制表示就是0xFF)。 - feof:它不是「预判下一个字符是不是EOF」,而是「告诉你:上一次的读操作已经触发了文件末尾的状态」。也就是说,只有当你尝试读取了一个不存在的字符之后,feof才会返回非0值(表示已经到EOF了)。
两段代码的差异分析
工作正常的代码
while (1) { char tempChar = fgetc(ptrInputFile); if (feof(ptrInputFile)) { break; } fprintf(ptrOutputFile, "%c", tempChar); }
这个逻辑是对的:
- 先尝试读一个字符
- 检查刚才的读操作是不是触发了EOF(也就是有没有读到不存在的内容)
- 如果没触发,说明读到的是有效字符,写入输出文件;如果触发了,直接跳出循环,不会把EOF写进去
哪怕是文件的最后一个字符,读完之后feof还是假,会正常写入;等下一次读的时候,fgetc返回EOF,feof变成真,直接break,完美避开多余字符。
出问题的代码
while (1) { if (feof(ptrInputFile)) { break; } char tempChar = fgetc(ptrInputFile); fprintf(ptrOutputFile, "%c", tempChar); }
问题就出在「先检查feof再读」的顺序上:
当文件指针已经停在最后一个有效字符的位置时,feof还是返回假(因为你还没尝试读这个字符之后的位置),所以会执行fgetc。这时候fgetc会尝试读下一个不存在的字符,返回EOF(也就是-1)。
如果你用的是有符号char,-1存在char里就是二进制的0xFF,然后你把这个值写入了输出文件,就出现了那个多余的0xFF。等写完之后,下一次循环检查feof才会返回真,这时候才break,但已经晚了!
额外的优化建议
其实更严谨的写法应该用int来存fgetc的返回值,同时直接判断是不是EOF,这样还能避免文件中有0xFF字符时和EOF混淆的问题:
int tempChar; // 必须用int,因为EOF是int类型 while ((tempChar = fgetc(ptrInputFile)) != EOF) { fprintf(ptrOutputFile, "%c", tempChar); } // 之后可以检查是正常到末尾还是读出错 if (ferror(ptrInputFile)) { printf("读文件出错了!"); }
内容的提问来源于stack exchange,提问作者user2982010
相关产品推荐
相关产品推荐

