为何在文件修改代码中需两次调用fseek(fp, i, SEEK_SET)?
为什么修改文件时需要两次调用fseek?
先看你提供的代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> void print_file_contents(const char *filename) { FILE *fp; char letter; if((fp=fopen(filename,"r+"))==NULL) { printf("error\n"); exit(1); } fseek(fp,0,SEEK_END); int size=ftell(fp); rewind(fp); for(int i=0;i<size;i++) { fseek(fp,i,SEEK_SET); letter=fgetc(fp); if((letter=='a') || (letter=='e') || (letter=='i')) { fseek(fp,i,SEEK_SET); // 为什么需要这个fseek? fwrite("5",1,sizeof(char),fp); } } fclose(fp); } int main(int argc, char *argv[]) { print_file_contents("myfile"); return 0; }
你疑惑的点在于:第一次fseek已经定位到第i个字符,用fgetc读取后,为什么还要再调用一次fseek才能写入?
原因很简单:fgetc会自动移动文件位置指示器。
具体流程拆解:
- 第一次
fseek(fp, i, SEEK_SET):把文件位置指示器精准定位到第i个字节的位置,准备读取这个字符。 letter = fgetc(fp):成功读取第i个字节后,指示器会自动向后移动1位,此时它指向的是第i+1个字节的位置。- 如果此时直接调用
fwrite,它会把"5"写入到i+1的位置,而不是覆盖原来的i位置——这就会导致原字符没被替换,反而在后面多插了一个"5",完全不符合需求。 - 所以第二次
fseek(fp, i, SEEK_SET)的作用,就是把指示器重新移回第i个字节的位置,让fwrite能准确覆盖掉原来的元音字符。
另外补充个C标准的细节:当你在同一个文件流上混合使用读取和写入操作时,必须用fseek或fflush来明确调整位置,否则行为是未定义的。哪怕你觉得位置“好像”是对的,也必须显式定位,保证操作的正确性。
内容的提问来源于stack exchange,提问作者void_brain
相关产品推荐
相关产品推荐

