C语言typedef结构体数组读取文件异常求助:文件无法打开且输出全零
问题排查与代码修正方案
核心错误分析
全局作用域放置执行语句
C语言规定,全局区域(函数外部)只能存在变量声明、宏定义、函数原型等静态代码,不能包含if代码块、函数调用这类可执行逻辑。你把文件打开和错误判断放在全局,这是导致编译失败的直接原因。缺少必要头文件
使用strerror()和errno需要包含<errno.h>头文件,否则会出现未定义标识符的编译错误。数据读取逻辑错误
GetData()函数中,首次读取name在循环外,后续循环只读取age和salary,没有读取下一条记录的name;同时循环条件判断fp是否非空无效,应该检查fscanf的返回值来确认读取是否成功。字符串转义错误
代码中字符串里的换行直接写了换行符,正确写法应该是用\n转义,否则会触发编译错误。输入合法性未校验
main()中读取用户输入的records_read时,没有判断是否超出实际读取的记录数,可能导致数组越界访问。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <errno.h> // 新增:用于strerror和errno #define SIZE 10 #define ARRAY_SIZE 30 // 定义结构体 typedef struct { char name[SIZE]; int age; int salary; } data; data a[ARRAY_SIZE]; // 全局结构体数组 // 读取数据函数 int GetData(FILE *fp) { int i = 0; // 循环读取每一条记录:name + age + salary while (i < ARRAY_SIZE) { // 检查是否成功读取三个字段 int ret = fscanf(fp, "%s %d %d", a[i].name, &a[i].age, &a[i].salary); if (ret != 3) { // 读取失败(到文件末尾或格式错误),退出循环 break; } i++; } return i; } // 打印数据函数 void ShowData(int records_read, int total_records) { // 校验输入的记录数是否合法 if (records_read < 1 || records_read > total_records) { printf("输入无效!请输入1到%d之间的数字\n", total_records); return; } // 打印指定数量的记录 for (int i = 0; i < records_read; i++) { printf("%s %d %d\n", a[i].name, a[i].age, a[i].salary); } } int main() { int total_records; int records_read; // 在main中打开文件(正确的执行位置) FILE *fp = fopen("DataFile.txt", "r"); if (fp == NULL) { printf("打开文件失败:%s\n", strerror(errno)); exit(1); } // 读取数据并获取总记录数 total_records = GetData(fp); if (total_records == 0) { printf("未读取到任何数据\n"); fclose(fp); return 0; } // 提示用户输入 printf("请输入1到%d之间的数字:", total_records); scanf("%d", &records_read); // 打印数据 ShowData(records_read, total_records); // 关闭文件 fclose(fp); return 0; }
关键修改说明
- 将文件打开和错误判断移至
main()函数内,符合C语言执行逻辑规范。 - 新增
<errno.h>头文件,解决strerror和errno的未定义问题。 - 重构
GetData()函数的读取逻辑,通过fscanf的返回值判断是否成功读取一条完整记录,确保每一条记录的name、age、salary都被正确读取。 - 在
ShowData()中新增输入合法性校验,避免数组越界。 - 修正字符串中的换行符为
\n,解决编译错误。
内容的提问来源于stack exchange,提问作者NotSoGoodAtThis
相关产品推荐
相关产品推荐

