使用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); }
错误排查
- 空指针非法操作:当
fopen失败返回NULL时,调用fclose(fp)属于未定义行为,空指针不能被关闭。 - 文件指针位置判断错误:第一次
fscanf读取%s %s %d后,文件指针停在第三个字段的分隔符(如换行、空格)处,此时fgetc读取的是分隔符而非EOF,会错误进入else分支,再次调用fscanf会读取失败,导致结构体成员值混乱。 - printf参数不匹配:else分支的
printf仅写了3个占位符,但传入了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
相关产品推荐
相关产品推荐

