读取score.txt文件中int数组失败,如何修复代码错误?
问题描述
读取score.txt文件中的int数组时触发错误,错误提示为:$ !ERROR: Wrong file format to 'score.txt',怀疑问题出在读取int score[3]的代码段,相关代码与文件内容如下:
C代码
// code typedef struct { int no; char name[TSIZE]; int score[3]; int sum; double avg; } Score; int num; if (fscanf(file, "%d%*c", &num) != 1){ printf("$ !ERROR: Wrong file format to num.\n"); exit(1); } *ptr_s_list = (Score *)malloc(sizeof(Score) * num); if (*ptr_s_list == NULL){ printf("$ !ERROR: Malloc failed.\n"); exit(1); } for (int s = 0; s < num; ++s){ if (fscanf(file, "%d%*c", &(*ptr_s_list)[*ptr_s_items].no) != 1 || fscanf(file, "%[^\n]%*c", (*ptr_s_list)[*ptr_s_items].name) != 1 || fscanf(file, "%d %d %d", &(*ptr_s_list)[*ptr_s_items].score[0], &(*ptr_s_list)[*ptr_s_items].score[1], &(*ptr_s_list)[*ptr_s_items].score[2]) != 1 || fscanf(file, "%d%*c", &(*ptr_s_list)[*ptr_s_items].sum) != 1 || fscanf(file, "%lf%*c", &(*ptr_s_list)[*ptr_s_items].avg) != 1 ){ printf("$ !ERROR: Wrong file format to '%s'.\n", filename); exit(1); } (*ptr_s_items)++; }
score.txt内容
// txt 3 // this int num 1 jay 100 90 80 270 90.0 2 key 90 80 65 235 78.3 3 ray 90 45 65 200 66.7
错误原因与修复方案
核心错误点
读取score[3]的fscanf判断逻辑完全错误:%d %d %d格式会尝试读取3个整数,成功时返回值为3,但你代码中判断!=1——只要读取结果不是1就触发错误,这直接导致读取分数数组时立刻触发格式错误提示。
除此之外还有几个次要问题会导致读取错位:
- 读取
name时使用%[^\n]%*c,会把当前行剩余的所有内容(包括分数、总分、平均分)全部读入name,因为%[^\n]会匹配到换行符前的所有字符,彻底打乱后续读取逻辑。 - 循环变量
s未被使用,反而依赖*ptr_s_items作为数组索引,若该变量初始值不正确,会导致数组越界或读取遗漏/重复。 - 手动添加的
%*c会干扰fscanf的空白处理:fscanf处理%d、%s、%lf等格式时会自动跳过空白字符(空格、制表符、换行),手动吃掉字符反而会导致读取错位。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define TSIZE 20 // 补充原代码缺失的TSIZE定义 typedef struct { int no; char name[TSIZE]; int score[3]; int sum; double avg; } Score; void read_scores(FILE *file, Score **ptr_s_list, int *ptr_s_items, const char *filename) { int num; // 读取num,依赖fscanf自动跳过空白,无需手动处理换行 if (fscanf(file, "%d", &num) != 1) { printf("$ !ERROR: Wrong file format to num.\n"); exit(1); } *ptr_s_list = (Score *)malloc(sizeof(Score) * num); if (*ptr_s_list == NULL) { printf("$ !ERROR: Malloc failed.\n"); exit(1); } *ptr_s_items = 0; // 初始化元素计数变量 for (int s = 0; s < num; ++s) { // 将整行数据的读取合并为一个fscanf,判断返回值是否为7(成功读取7个字段) if (fscanf(file, "%d %s %d %d %d %d %lf", &(*ptr_s_list)[s].no, (*ptr_s_list)[s].name, &(*ptr_s_list)[s].score[0], &(*ptr_s_list)[s].score[1], &(*ptr_s_list)[s].score[2], &(*ptr_s_list)[s].sum, &(*ptr_s_list)[s].avg) != 7) { printf("$ !ERROR: Wrong file format to '%s'.\n", filename); exit(1); } (*ptr_s_items)++; } }
关键修改说明
- 修正分数数组读取的判断逻辑:将分数数组读取的返回值判断从
!=1改为整行读取的返回值等于7(或单独读取分数时判断等于3),确保只有当字段读取失败时才触发错误。 - 修正姓名读取方式:使用
%s读取姓名,因为文件中姓名是无空格的单个字符串,%s会自动跳过前面的空白,读取到下一个空白字符为止,不会误读后续内容。 - 移除不必要的
%*c:依赖fscanf的自动空白跳过机制,避免手动处理字符导致的读取错位。 - 规范循环索引使用:用循环变量
s作为数组索引,同时初始化*ptr_s_items为0,避免索引错误。 - 补充缺失的宏定义:添加
TSIZE的定义,解决原代码的编译错误。
内容的提问来源于stack exchange,提问作者user21494777
相关产品推荐
相关产品推荐

