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

使用fscanf读取文件到结构体并输出时出现异常结果的问题排查

问题描述

我尝试用fscanf读取文件内容到结构体成员,再通过printf输出。文件有两种格式:

d asd 12

或

d asd 12 cash

结构体定义如下:

typedef struct customer
{
    char cname[20];
    char address[30];
    int units;
    char mode_of_payment[10];
} custo;

display函数接收文件名,需根据文件内容格式输出,但实际输出异常:

----------------------------------------
Customer details are as follows
in firstp²a ☺ 0

期望输出为:

in first d asd 12

或

in second d asd 12 cash

原display函数代码:

int display(char file_name[])
{
    printf("\n****************************************\n");
    FILE *fp;
    char ch;
    custo c;
    fp = fopen(file_name,"r");
    
    if (fp == NULL)
    {
        printf("\nFile name dose not exist\n");
        fclose(fp);
    }
    else
    {
        fscanf(fp,"%s %s %d",c.cname,c.address,&c.units);
        printf("Customer details are as follows\n");
        ch=fgetc(fp);
        if(ch==EOF){
            printf("in first");
            printf("%s %s %d", c.cname, c.address, c.units);
        }
        else{
            printf("in second");
            fscanf(fp,"%s %s %d %s",c.cname,c.address,&c.units,c.mode_of_payment);
            printf("%s %s %d", c.cname, c.address, c.units, c.mode_of_payment);
        }
    }
    fclose(fp);
}
错误排查
  1. 空指针非法操作:当fopen失败返回NULL时,调用fclose(fp)属于未定义行为,空指针不能被关闭。
  2. 文件指针位置判断错误:第一次fscanf读取%s %s %d后,文件指针停在第三个字段的分隔符(如换行、空格)处,此时fgetc读取的是分隔符而非EOF,会错误进入else分支,再次调用fscanf会读取失败,导致结构体成员值混乱。
  3. printf参数不匹配:else分支的printf仅写了3个占位符,但传入了4个参数,会引发输出异常。
  4. 未处理多行数据:原代码仅读取一行数据,无法处理文件中多行内容。
修复后的代码
#include <stdio.h>

typedef struct customer
{
    char cname[20];
    char address[30];
    int units;
    char mode_of_payment[10];
} custo;

int display(char file_name[])
{
    printf("\n****************************************\n");
    FILE *fp;
    custo c;
    int read_result;

    fp = fopen(file_name, "r");
    if (fp == NULL)
    {
        printf("\nFile does not exist\n");
        return -1;
    }

    printf("Customer details are as follows\n");
    // 循环读取文件所有行
    while (1)
    {
        // 先尝试读取带支付方式的4字段格式
        read_result = fscanf(fp, "%s %s %d %s", c.cname, c.address, &c.units, c.mode_of_payment);
        if (read_result == 4)
        {
            printf("in second %s %s %d %s\n", c.cname, c.address, c.units, c.mode_of_payment);
            continue;
        }
        // 读取4字段失败,尝试读取3字段基础格式
        else if (read_result == 3)
        {
            printf("in first %s %s %d\n", c.cname, c.address, c.units);
            continue;
        }
        // 读取不足3字段,判断是否到文件末尾
        else if (feof(fp))
        {
            break;
        }
        // 其他读取错误
        else
        {
            printf("Error reading file\n");
            break;
        }
    }

    fclose(fp);
    return 0;
}
修复说明
  • 移除空指针时的fclose调用,打开失败直接返回错误码。
  • 利用fscanf的返回值判断读取字段数:返回4则为带支付方式的格式,返回3则为基础格式,无需手动判断文件指针位置。
  • 修正printf占位符与参数不匹配的问题。
  • 添加循环逻辑,支持读取文件中所有行数据。
  • 增加读取错误和文件末尾的判断,逻辑更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 15:12:36