C语言结构体实现学生信息存文件:首行输出异常求助
问题:C语言学生信息写入文件首行异常排查与解决
问题概述
编写了一段C语言代码,通过结构体存储学生信息并写入文件,功能是接收学生列表并保存,但生成的文件首行内容显示异常。
原代码
#include <stdio.h> #include <comip.h> #define MAX_STR_LEN 80 int main() { //creating file FILE *students_file; students_file = fopen("students_file.txt", "w"); int students_num; puts("How many students do you have ? : "); scanf("%d", &students_num); struct students { char first_name[MAX_STR_LEN]; char last_name[MAX_STR_LEN]; char id[12]; float average; }; struct students *students = calloc(students_num, sizeof *students); fprintf(students_file, "number id firstname lastname average\n"); for (int i = 1; i <= students_num; i++) { printf("Please enter student #%d first name : ", i); scanf("%79s", students[i].first_name); printf("Please enter student #%d last name : ", i); scanf("%79s", students[i].last_name); printf("Please enter student #%d id : ", i); scanf("%79s", students[i].id); printf("Please enter student #%d average : ", i); scanf("%f", &students[i].average); fprintf(students_file, "#%d.\t %s\t %s\t %s\t %f\n", i, students[i].id, students[i].first_name, students[i].last_name, students[i].average); } fclose(students_file); return 0; }
输入数据
> How many students do you have ? : 3 Please enter student #1 first name : mani Please enter student #1 last name : aghaie Please enter student #1 id : 1383ma Please enter student #1 average : 19.72 Please enter student #2 first name : arash Please enter student #2 last name : hamidi Please enter student #2 id : 1384ah Please enter student #2 average : 14.27 Please enter student #3 first name : pourya Please enter student #3 last name : ghorbani Please enter student #3 id : 1382pg Please enter student #3 average : 16.52
异常现象
生成的文件首行出现乱码/异常字符,格式错乱。
问题排查
- 头文件错误:引入了无关的
<comip.h>(Windows COM组件头文件),但未包含calloc所需的<stdlib.h>,导致calloc函数声明缺失,返回值被错误解析,可能造成内存分配异常。 - 数组下标越界:C语言数组下标从0开始,
calloc分配了students_num个元素的数组,有效下标范围是0到students_num-1,但循环中使用i从1到students_num访问students[i],属于越界访问,触发未定义行为,会破坏内存中的数据(包括文件流的内部状态),进而导致文件首行写入异常。 - 未检查资源分配结果:未检查
fopen和calloc的返回值,若文件打开失败或内存分配失败,会导致后续操作出错。
解决方案
- 替换头文件:移除
<comip.h>,添加<stdlib.h>以正确使用calloc。 - 修正数组下标:将循环调整为从
0开始,或访问时使用i-1作为下标,确保在有效范围内访问数组元素。 - 添加错误检查:检查
fopen和calloc的返回值,避免空指针操作。
修正后的代码
#include <stdio.h> #include <stdlib.h> #define MAX_STR_LEN 80 int main() { FILE *students_file = fopen("students_file.txt", "w"); if (!students_file) { perror("Failed to open file"); return 1; } int students_num; puts("How many students do you have ? : "); if (scanf("%d", &students_num) != 1 || students_num <= 0) { puts("Invalid number of students"); fclose(students_file); return 1; } typedef struct { char first_name[MAX_STR_LEN]; char last_name[MAX_STR_LEN]; char id[12]; float average; } Student; Student *students = calloc(students_num, sizeof(Student)); if (!students) { perror("Failed to allocate memory"); fclose(students_file); return 1; } fprintf(students_file, "number id firstname lastname average\n"); for (int i = 0; i < students_num; i++) { printf("Please enter student #%d first name : ", i+1); scanf("%79s", students[i].first_name); printf("Please enter student #%d last name : ", i+1); scanf("%79s", students[i].last_name); printf("Please enter student #%d id : ", i+1); scanf("%11s", students[i].id); // 限制输入长度避免id数组越界 printf("Please enter student #%d average : ", i+1); scanf("%f", &students[i].average); fprintf(students_file, "#%d.\t %s\t %s\t %s\t %.2f\n", i+1, students[i].id, students[i].first_name, students[i].last_name, students[i].average); } free(students); fclose(students_file); return 0; }
额外优化:限制id的输入长度为11(因为id数组长度是12,留一个位置存字符串结束符),输出浮点数时保留两位小数更美观,添加了内存释放操作避免内存泄漏。
内容的提问来源于stack exchange,提问作者Mani Aghaie
相关产品推荐
相关产品推荐

