You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在文件修改代码中需两次调用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会自动移动文件位置指示器。

具体流程拆解:

  1. 第一次fseek(fp, i, SEEK_SET):把文件位置指示器精准定位到第i个字节的位置,准备读取这个字符。
  2. letter = fgetc(fp):成功读取第i个字节后,指示器会自动向后移动1位,此时它指向的是第i+1个字节的位置。
  3. 如果此时直接调用fwrite,它会把"5"写入到i+1的位置,而不是覆盖原来的i位置——这就会导致原字符没被替换,反而在后面多插了一个"5",完全不符合需求。
  4. 所以第二次fseek(fp, i, SEEK_SET)的作用,就是把指示器重新移回第i个字节的位置,让fwrite能准确覆盖掉原来的元音字符。

另外补充个C标准的细节:当你在同一个文件流上混合使用读取和写入操作时,必须用fseek或fflush来明确调整位置,否则行为是未定义的。哪怕你觉得位置“好像”是对的,也必须显式定位,保证操作的正确性。

内容的提问来源于stack exchange,提问作者void_brain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 23:55:26