C语言如何将int类型值写入二进制文件和txt文件
错误原因梳理
- 核心错误:
scanf传参不符合要求。scanf读入int类型值时需要传入目标变量的地址,原代码写为scanf("%d", last->stuNum);,而last->stuNum是未初始化的int类型随机值,既导致输入的学号没有写入到结构体的对应成员中,也使得后续写入索引文件的last->stuNum是内存垃圾值,就是你观察到的66955608268424这类异常大数。 - 重复打开文件且文件名不匹配:main函数中已经打开了对应索引和数据文件,但
newStudent函数内又重新打开了名称不同的另外两个文件,覆盖了传入的文件指针。不仅造成资源泄漏,还导致main函数最终关闭的不是实际写入数据的文件指针,缓冲区内容无法正常刷新到磁盘。 - 结构体未完全初始化:仅对stuNum赋值,point成员是未初始化的垃圾值,写入二进制文件后会产生无效数据。
- 内存与文件资源泄漏:malloc申请的结构体内存没有释放,
newStudent内打开的文件指针也没有关闭。
额外说明:二进制数据文件用文本编辑器打开显示乱码是正常现象,只要后续通过
fread按struct student的固定大小读取,能拿到正确的学号、分数就符合设计要求,不属于错误。
修复方案
调整后的完整代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> struct student { int stuNum; int point; }; int newStudent(FILE* dataf, FILE* indexf); int main(void) { FILE* datafile; FILE* indexfile; // 统一文件名,索引用txt,数据用bin,a+模式支持追加写入,适合多次添加学生 indexfile = fopen("index.txt", "a+"); // 二进制文件用ab+模式,支持追加和读取,不会清空原有内容 datafile = fopen("data.bin", "ab+"); if (indexfile == NULL || datafile == NULL) { printf("文件打开失败\n"); return -1; } newStudent(datafile, indexfile); fclose(datafile); fclose(indexfile); return 0; } int newStudent(FILE* dataf, FILE* indexf) { // 去掉重复打开文件的逻辑,直接使用传入的文件指针 struct student* last = (struct student*)malloc(sizeof(struct student)); if (last == NULL) { printf("内存申请失败\n"); return -1; } printf("输入学生学号:\n"); // 修正scanf传参,添加取地址符 scanf("%d", &(last->stuNum)); // 初始化分数,可根据需求扩展录入分数的逻辑 last->point = 0; // 索引可追加存储数据偏移量,方便后续快速查找,这里示例存储学号+对应数据在bin文件的偏移 long offset = ftell(dataf); fprintf(indexf, "%d\t%ld\n", last->stuNum, offset); // 写入结构体到二进制文件 fwrite(last, sizeof(struct student), 1, dataf); // 释放申请的内存 free(last); return 0; }
关键修复点说明
- 修正了
scanf的传参错误,添加取地址符,确保输入的学号正确写入结构体成员 - 删除了
newStudent内重复打开文件的逻辑,统一使用main函数打开的文件指针,避免资源泄漏和文件名不一致问题 - 补充了内存申请失败、文件打开失败的异常判断,提升代码健壮性
- 初始化了point成员,避免写入无效垃圾值
- 优化了索引文件的存储逻辑,追加了二进制数据的偏移量,符合索引的设计目的,方便后续快速定位学生数据
- 补充了动态内存的释放逻辑,避免内存泄漏
内容的提问来源于stack exchange,提问作者pel oz
相关产品推荐
相关产品推荐

