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

fseek()使用不当致二进制文件员工薪资更新循环无法终止?

解决二进制文件更新员工薪资时循环无法终止的问题

我明白你遇到的困扰了——在更新二进制文件里的员工薪资时,明明只有2名员工,循环却一直停不下来,核心问题出在文件指针的处理和循环条件的判断上。咱们一步步拆解:

原代码的问题分析

先看你最初的实现:

void updateSalary(char* filename) { 
    int i = 0; 
    employee temp; 
    char c; 
    float increase; 
    FILE *fup = fopen(filename, "rb+"); 
    if (fup == NULL) { 
        printf("Unable to read the file\n"); 
        return; 
    } 
    fread(&temp, sizeof(employee), 1, fup); 
    while (!feof(fup)) { 
        printf("How big is the increase to %s's salary?\n", temp.name); 
        scanf("%f", &increase); 
        temp.salary += increase; 
        fseek(fup, (i * sizeof(employee)), SEEK_SET); 
        fwrite(&temp, sizeof(employee), 1, fup); 
        fread(&temp, sizeof(employee), 1, fup); 
        i++; 
    } 
    fclose(fup); 
}

这里有两个关键问题:

  1. while (!feof(fup))的逻辑陷阱:feof()只有在你尝试读取超出文件末尾之后,才会被置为真。这意味着当你读完最后一条记录后,还会再进入一次循环,触发不必要的操作,甚至导致循环无法正常终止。
  2. 文件指针定位错误:写完当前记录后,fwrite确实会移动文件指针,但原代码没有确保写完后指针指向了下一条记录的起始位置,加上feof的问题,直接导致循环停不下来。

修正后的代码及解释

你调整后的代码已经解决了核心问题,我再帮你梳理下关键修正点:

void updateSalary(char* filename, float threshold) { 
    int i = 0; 
    employee temp; 
    char c; 
    float increase; 
    FILE *fup = fopen(filename, "r+b"); 
    if (fup == NULL) { 
        printf("Unable to read the file\n"); 
        return; 
    } 
    //fread(&temp, sizeof(employee), 1, fup); 
    while (fread(&temp, sizeof(employee), 1, fup)) { 
        printf("How big is the increase to %s's salary?\n", temp.name); 
        rewind(stdin); 
        scanf("%f", &increase); 
        temp.salary += increase; 
        fseek(fup, (i * sizeof(employee)), SEEK_SET); 
        fwrite(&temp, sizeof(employee), 1, fup); 
        fseek(fup, ((i+1) * sizeof(employee)), SEEK_SET); // 关键修正
        i++; 
    } 
    fclose(fup); 
}

核心改进点:

  • 循环条件改为while (fread(...)):直接用fread的返回值判断是否成功读取到记录,只要读取失败(到文件末尾)就立即退出循环,完美避开了feof的陷阱。
  • 手动定位下一条记录:在fwrite之后添加了fseek(fup, ((i+1) * sizeof(employee)), SEEK_SET);,强制把文件指针移到下一条员工记录的起始位置,确保下一次fread能正确读取下一个员工。
  • 清除输入缓冲区:rewind(stdin);用来清除scanf可能残留的换行符或其他输入垃圾,避免后续读取出现异常。
  • 移除冗余的初始fread:因为循环条件里已经包含了第一次读取,不需要额外提前读一次。

这样调整后,循环就会在处理完所有员工记录后准确终止,不会出现无限循环的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:04:27