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

C语言文件读取逻辑错误排查:fgets读取员工数据异常

员工数据文件读取异常问题排查与解决

问题背景

用户编写了C语言函数读取包含字符串和浮点值的员工数据文件,运行后出现输出异常,怀疑问题与fgets、strtok的使用有关,且希望仅使用fgets实现读取逻辑,不使用fscanf。

用户原代码

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

typedef struct
{
    char Name[100];
    char Title;
    double Hours_Worked;
    double Pay_Rate;
    double Payment;
} Employee;

void Read_Records_From_File(FILE *Read_File, Employee *Payroll)
{
    int Index;
    char First_Name[100], Last_Name[100];
    
    Index = 0;
    
    while (!feof(Read_File))
    {
        fgets(Payroll[Index].Name, 100, Read_File);
        strtok(Payroll[Index].Name, "\n");
        
        fscanf(Read_File, "%c", &Payroll[Index].Title);
        
        fscanf(Read_File, "%lf", &Payroll[Index].Hours_Worked);
        fscanf(Read_File, "%lf", &Payroll[Index].Pay_Rate);
        
        printf("Name : %s", Payroll[Index].Name);
        printf("\nTitle : %c", Payroll[Index].Title);
        printf("\nHours Worked : %lf", Payroll[Index].Hours_Worked);
        printf("\nPay Rate : %lf", Payroll[Index].Pay_Rate);
        puts("\n");
        
        Index += 1;
    }
}

int main(void)
{
    FILE *Read_File;
    Employee Payroll[100];
    
    Read_File = fopen("Payroll.txt", "r");
    
    Read_Records_From_File(Read_File, &Payroll);
}

数据文件内容(Payroll.txt)

SurName1 FirstName1
B
40.0
12.0
SurName2 FirstName2
M
35.0
20.0

异常输出

Name : SurName1 FirstName1
Title : B
Hours Worked : 40.000000
Pay Rate : 12.000000

Name : 

Title : S
Hours Worked : 0.000000
Pay Rate : 0.000000

Name : urName2 FirstName2
Title : M
Hours Worked : 35.000000
Pay Rate : 20.000000

Program ended with exit code: 0

问题原因分析

  • feof循环条件错误:while (!feof(Read_File))会导致多执行一次循环。feof仅在尝试读取超出文件末尾时才会置位,因此最后一次循环会读取无效数据,出现空Name和错误的Title。
  • fscanf残留换行符干扰:fscanf读取字符和数值后,文件指针会停留在换行符前,下一次fgets会直接读取这个空换行,导致Name字段为空;后续读取Title时,会读到下一行的第一个字符(如S),引发连锁错误。
  • strtok用法不严谨:strtok(Payroll[Index].Name, "\n")虽然能去除换行符,但如果fgets读取的字符串刚好填满缓冲区且没有换行,该操作会破坏字符串;且未保存返回值,写法不安全。

解决方案(仅用fgets实现)

修改读取逻辑,全部用fgets读取每行数据,再用sscanf解析数值,同时修正循环条件和换行符处理:

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

typedef struct
{
    char Name[100];
    char Title;
    double Hours_Worked;
    double Pay_Rate;
    double Payment;
} Employee;

void Read_Records_From_File(FILE *Read_File, Employee *Payroll)
{
    int Index = 0;
    char buffer[100]; // 临时缓冲区存储非字符串字段
    
    // 用fgets返回值判断是否读取成功,替代feof
    while (fgets(Payroll[Index].Name, sizeof(Payroll[Index].Name), Read_File))
    {
        // 用strcspn安全去除换行符:找到换行符位置,替换为'\0'
        Payroll[Index].Name[strcspn(Payroll[Index].Name, "\n")] = '\0';
        
        // 读取Title行
        if (!fgets(buffer, sizeof(buffer), Read_File)) break;
        // 从缓冲区解析单个字符,忽略换行
        sscanf(buffer, "%c", &Payroll[Index].Title);
        
        // 读取Hours_Worked行
        if (!fgets(buffer, sizeof(buffer), Read_File)) break;
        sscanf(buffer, "%lf", &Payroll[Index].Hours_Worked);
        
        // 读取Pay_Rate行
        if (!fgets(buffer, sizeof(buffer), Read_File)) break;
        sscanf(buffer, "%lf", &Payroll[Index].Pay_Rate);
        
        // 输出验证
        printf("Name : %s\n", Payroll[Index].Name);
        printf("Title : %c\n", Payroll[Index].Title);
        printf("Hours Worked : %.2lf\n", Payroll[Index].Hours_Worked);
        printf("Pay Rate : %.2lf\n\n", Payroll[Index].Pay_Rate);
        
        Index++;
        // 防止数组越界
        if (Index >= 100) break;
    }
}

int main(void)
{
    FILE *Read_File;
    Employee Payroll[100];
    
    Read_File = fopen("Payroll.txt", "r");
    // 增加文件打开失败检查
    if (!Read_File)
    {
        printf("无法打开文件\n");
        return 1;
    }
    
    Read_Records_From_File(Read_File, Payroll);
    fclose(Read_File); // 关闭文件
    
    return 0;
}

修改要点说明

  1. 循环条件修正:用fgets的返回值作为循环判断,当返回NULL时立即终止循环,避免读取无效数据。
  2. 统一用fgets读取:所有字段都通过fgets读取整行,彻底解决fscanf残留换行符的问题;非字符串字段先存入临时缓冲区,再用sscanf解析。
  3. 安全去除换行符:用strcspn替代strtok,直接定位换行符位置并替换为结束符,无论fgets是否读到换行都能安全处理。
  4. 增加错误检查:判断文件是否成功打开,防止空指针操作;读取每行时检查fgets返回值,避免文件中途结束导致的错误;限制数组索引,防止越界。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 18:06:00