如何在C语言中读写结构体数组至二进制文件?代码问题求助
问题修复与优化方案
关键问题拆解
你的代码存在四个核心问题:
fwrite参数的正确性疑问fgetpos/fsetpos的错误使用导致数据覆盖- 文件打开逻辑冗余且存在崩溃风险
- 读取函数中
feof的误用导致无效数据读取
逐一修复说明
1. fwrite中&符号的必要性
october[counter]是struct cinema类型的实体对象,fwrite要求传入数据的起始地址(const void*类型)。因此必须使用&october[counter]来获取结构体的地址,你的原写法是正确的。也可以写成october + counter,两者等价。
2. 移除多余的fgetpos/fsetpos操作
你每次调用new_cinema都会重新打开文件,而:
- 使用
ab模式打开文件时,文件指针默认定位在文件末尾,无需手动调整 - 保存并复用
current_position会导致后续写入覆盖之前的数据,完全是多余且危险的操作。直接删除所有fgetpos和fsetpos相关代码即可。
3. 写入函数的优化与修复
原文件打开逻辑冗余,且错误处理存在崩溃风险(fopen_s失败时调用fclose(NULL))。优化后的代码如下:
#include <stdio.h> #include <stdlib.h> #define N 25 // 补充缺失的宏定义 struct cinema { char name[256]; char session[256]; double price; int audience; }; struct cinema october[N]; int counter = 0; void new_cinema() { if (counter >= N) { printf("\nThe limit has gone!\n"); return; } FILE* file; // 使用局部文件指针替代全局指针,避免资源冲突 if (fopen_s(&file, "file.bin", "ab") != 0) { printf("\nError opening file!\n"); return; } // 清除之前scanf残留的换行符,避免gets_s直接读取空行 while(getchar() != '\n'); printf("\nWrite the name of the movie:\n"); gets_s(october[counter].name, 255); printf("\nEnter the session time:\n"); scanf_s("%s", october[counter].session, 255); printf("\nEnter ticket price:\n"); scanf_s("%lf", &october[counter].price); printf("\nEnter the number of viewers:\n"); scanf_s("%d", &october[counter].audience); // 写入结构体数据,校验写入结果 if (fwrite(&october[counter], sizeof(struct cinema), 1, file) != 1) { printf("\nFailed to write data!\n"); } else { counter++; } fclose(file); }
4. 读取函数的修复
原读取函数使用while(!feof(file))会导致多读取一次空数据(feof仅在读取失败后才会置位),同时需要优化内存分配和遍历逻辑:
void read_struct() { FILE* file; if (fopen_s(&file, "file.bin", "rb") != 0) { printf("\nCouldn't read the file!\n"); return; } struct cinema *testing = malloc(sizeof(struct cinema) * N); if (testing == NULL) { printf("\nMemory allocation failed!\n"); fclose(file); return; } int read_count = 0; // 以fread的返回值作为循环条件,判断是否成功读取一个结构体 while (fread(&testing[read_count], sizeof(struct cinema), 1, file) == 1) { read_count++; } // 仅遍历实际读取到的数据 for (int i = 0; i < read_count; i++) { printf("\nMovie Name: %s\n", testing[i].name); printf("Session Time: %s\n", testing[i].session); printf("Ticket Price: %.2lf\n", testing[i].price); printf("Number of Viewers: %d\n", testing[i].audience); } free(testing); fclose(file); }
额外注意事项
- 必须补充
#define N 25,否则原代码中的数组定义和条件判断会报错 - 减少全局变量的使用,可将
october和counter改为局部变量或通过函数参数传递 - 输入缓冲区的清理:
scanf_s读取后残留的换行符会干扰gets_s,必须手动清空 - 二进制文件跨平台兼容性:结构体的内存对齐依赖编译器和平台,若需跨平台需手动序列化数据
内容的提问来源于stack exchange,提问作者Kr1sp0
相关产品推荐
相关产品推荐

