C语言中如何检查、读取、创建二进制文件存储struct结构体数据
C语言实现学校信息结构体二进制读写与启动校验
需求与卡点
开发C语言程序需实现以下启动流程:
- 程序启动时检查是否存在已存储的历史学校信息结构体数据
- 无有效历史数据则引导用户录入,录入完成后写入磁盘存储,再进入主流程
- 有有效历史数据则直接加载到内存数组,跳过录入环节
开发时为首次接触C语言文件操作,存在两个核心未解决问题: - 无法确定main函数中判断“是否存在有效历史数据”的条件写法
- 不清楚二进制读写的
safe(保存)和read(读取)函数实现逻辑
现有代码框架
#define MAX_ESCOLA 5 typedef struct{ int identificardor; char nome_escola[30]; char localidade_escola[20]; }t_inserir_escola; void registar_escolas(t_inserir_escola vetor_adicionar_escola[]); void safe(t_inserir_escola vetor_adicionar_escola[]); void read(t_inserir_escola vetor_adicionar_escola[]); int main() { int numero_questionario = 0; t_inserir_escola vetor_adicionar_escola[MAX_ESCOLA]; if(/* 待实现判断条件 */) { registar_escolas(vetor_adicionar_escola); safe(vetor_adicionar_escola); }else printf("\n|dados já inseridos|"); // 后续主流程预留 //t_inquerido vetor_inqueridos[MAX_QUESTIONARIO]; //menu(vetor_inqueridos, numero_questionario, vetor_adicionar_escola, vetor_adicionar_escola); return 0; } void safe(t_inserir_escola vetor_adicionar_escola[]) { // 待实现 } void read(t_inserir_escola vetor_adicionar_escola[]) { // 待实现 }
落地实现方案
所有逻辑基于二进制文件escolas.dat(程序同级目录)实现,无需第三方依赖。
1. 补充常量定义
在现有宏定义下方新增文件路径常量,方便统一修改:
#define FILE_PATH "escolas.dat" // 存储学校数据的二进制文件路径
2. main函数判断逻辑实现
核心思路:不单纯校验文件是否存在,而是同时校验文件大小是否符合预设值,避免损坏/空文件导致的读取异常:
// 替换main中原有if判断的完整逻辑 FILE *fp = fopen(FILE_PATH, "rb"); int need_input = 0; if (fp == NULL) { // 文件打开失败(不存在/无权限),需要重新录入 need_input = 1; } else { // 文件打开成功,校验文件大小是否合法 fseek(fp, 0, SEEK_END); // 指针移到文件末尾 long file_size = ftell(fp); // 获取文件总字节数 fclose(fp); // 合法大小 = 单个结构体大小 * 最大存储学校数 if (file_size != sizeof(t_inserir_escola) * MAX_ESCOLA) { // 大小不匹配,视为无效数据,需要重新录入 need_input = 1; } } if (need_input) { registar_escolas(vetor_adicionar_escola); safe(vetor_adicionar_escola); } else { printf("\n|dados já inseridos|"); read(vetor_adicionar_escola); // 加载历史数据到内存数组 }
注意:
fseek和ftell仅用于计算文件大小,不会修改文件内容;二进制模式打开可以避免Windows平台下换行符转义导致的大小计算偏差。
3. safe保存函数实现
通过fwrite一次性将整个结构体数组写入二进制文件:
void safe(t_inserir_escola vetor_adicionar_escola[]) { // 以二进制写入模式打开,覆盖原有内容 FILE *fp = fopen(FILE_PATH, "wb"); if (fp == NULL) { perror("保存失败"); // 直接打印系统层面的错误原因(磁盘满、无权限等) return; } // fwrite参数:数据起始指针、单个元素大小、元素总个数、文件指针 fwrite(vetor_adicionar_escola, sizeof(t_inserir_escola), MAX_ESCOLA, fp); fclose(fp); printf("\n数据保存完成\n"); }
4. read读取函数实现
通过fread一次性将文件内容读入传入的结构体数组:
void read(t_inserir_escola vetor_adicionar_escola[]) { FILE *fp = fopen(FILE_PATH, "rb"); if (fp == NULL) { perror("读取失败"); return; } // fread参数和fwrite一致,读取的内容直接填充到传入的数组内存中 fread(vetor_adicionar_escola, sizeof(t_inserir_escola), MAX_ESCOLA, fp); fclose(fp); }
注意:二进制直接读写结构体的前提是,程序在同一编译环境下运行,不同编译器/不同平台的内存对齐规则可能不一致,会导致读取到乱码;普通本地桌面程序使用该方式无兼容性问题。
内容的提问来源于stack exchange,提问作者tiago gomes
相关产品推荐
相关产品推荐

