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

C语言反向操作文件定位并修改指定年龄人员信息的问题求助

提问内容

我有一个存储了姓名、姓氏和年龄的文件,内容如下:

john doe 20
lionel messi 33
cristiano ronaldo 35

我想要实现的功能是根据年龄查询到指定人员,再修改其任意信息。下方示例代码中,我尝试查找年龄为35的人员并修改其年龄值:

#include <stdio.h>
#include <string.h>

int main () {
    char line[30];
    FILE *fp;
    int age;
    if (!(fp = fopen("test.txt", "rb"))) {  /* 校验文件是否成功打开用于读取 */
        perror ("file open failed");
        return;
    }
    char name[20], surname[20];
    
    while (fgets (line, 30, fp)) {
        int off = 0;
        while (sscanf (line, "%s%s%d%n", name, surname, &age, &off) == 3) {
            if(age == 35) {
                fseek(fp,-2, SEEK_CUR);
                printf("%s", name);
                fprintf(fp, "%d", 19);
            }
            strcpy(line, line+off);
        }
    }
    fclose(fp);
    return 0;
}

但代码运行不符合预期,有时能成功更新信息有时不行。


解答

问题根因

  • 文件打开模式错误:你使用的rb是只读模式,没有写入权限,fprintf写入操作会直接失效,这是核心问题。
  • 读写交替未做状态切换:C语言标准明确规定,同一文件流上交替执行读、写操作时,两次操作中间必须调用fflush()或者文件定位类函数(fseek/fsetpos/rewind)切换流状态,否则行为完全未定义,这就是代码时好时坏的直接原因。
  • 回退字节数逻辑硬编码不兼容:固定回退2个字节的写法只适用于年龄刚好是2位、换行符长度符合预期的场景,一旦年龄是1位/3位、或者不同系统换行符长度不同(Windows是2字节,Linux是1字节),定位就会直接错位。
  • 直接修改原文件风险高:如果修改后的内容长度和原内容不一致,会直接覆盖相邻行的内容,导致文件损坏。

正确实现方案

推荐用「读原文件+写临时文件+替换原文件」的方案,逻辑简单容错率高,不会出现定位错误的问题:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main () {
    char line[100];
    FILE *fp, *tmp_fp;
    int age;
    char name[20], surname[20];
    int target_age = 35, new_age = 19;

    // 打开原文件读
    if (!(fp = fopen("test.txt", "r"))) {
        perror("原文件打开失败");
        return 1;
    }
    // 打开临时文件写
    if (!(tmp_fp = fopen("tmp_test.txt", "w"))) {
        perror("临时文件创建失败");
        fclose(fp);
        return 1;
    }
    
    while (fgets(line, sizeof(line), fp)) {
        // 解析当前行内容
        if (sscanf(line, "%s %s %d", name, surname, &age) == 3) {
            if (age == target_age) {
                // 匹配到目标行,写修改后的内容
                fprintf(tmp_fp, "%s %s %d\n", name, surname, new_age);
                continue;
            }
        }
        // 没匹配到的行原样写入临时文件
        fputs(line, tmp_fp);
    }

    fclose(fp);
    fclose(tmp_fp);

    // 替换原文件
    remove("test.txt");
    rename("tmp_test.txt", "test.txt");
    return 0;
}

如果你一定要直接在原文件上修改,需要把打开模式改成r+b(读写二进制模式),并且每次写入前确认定位的偏移量准确,读写操作之间加定位操作切换状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:24:00