C语言typedef结构体:结构体传参及文件读写错误排查
C语言结构体二进制读写问题修正
核心错误修正
1. 函数传参类型不匹配
save_dino和load_dino的第一个参数要求是dino*(结构体指针),你传入的是结构体变量d0、d1,必须用取地址符&获取指针后传入:
save_dino(&d0, fn); load_dino(&d1, fn);
2. 指针访问结构体成员语法错误
当变量是结构体指针时,必须用->访问成员,而非.。例如把d.lat改为d->lat,d.name改为d->name。
隐藏致命错误修正
3. 字符串指针未分配内存
结构体中的char *name仅为指针,未指向有效内存空间,直接调用strcpy会触发内存访问错误。需先为其分配足够内存:
// 为d0.name分配内存,长度为字符串长度+1(存储终止符'\0') d0.name = malloc(strlen("Aves indet.") + 1); strcpy(d0.name, "Aves indet.");
4. 二进制读写字符串逻辑错误
- 写入时需先保存字符串长度,否则读取时无法确定要读取的字节数:
// save_dino中写入字符串逻辑 size_t name_len = strlen(d->name); fwrite(&name_len, sizeof(size_t), 1, fp); fwrite(d->name, name_len, 1, fp);
- 读取时先获取长度,再分配内存后读取内容:
// load_dino中读取字符串逻辑 size_t name_len; fread(&name_len, sizeof(size_t), 1, fp); d->name = malloc(name_len + 1); fread(d->name, name_len, 1, fp); d->name[name_len] = '\0'; // 手动添加字符串终止符
5. fread参数错误
fread的第一个参数是内存地址,你直接传入d->lat(值),应改为传入地址&d->lat:
fread(&d->lat, sizeof(double), 1, fp); fread(&d->lng, sizeof(double), 1, fp);
6. 避免feof误用
feof作为循环条件会导致多读一次,且二进制文件不适合用fscanf读取,统一用fread按字节操作即可。
完整修正代码
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Dino { double lat; double lng; char *name; } dino; void save_dino(dino *d, char *ofn) { FILE *fp = fopen(ofn, "wb"); if (!fp) { // 增加文件打开失败判断 perror("fopen save failed"); return; } // 写入经纬度 fwrite(&d->lat, sizeof(double), 1, fp); fwrite(&d->lng, sizeof(double), 1, fp); // 写入字符串长度和内容 size_t name_len = strlen(d->name); fwrite(&name_len, sizeof(size_t), 1, fp); fwrite(d->name, name_len, 1, fp); fclose(fp); } void load_dino(dino *d, char *ifn) { FILE *fp = fopen(ifn, "rb"); if (!fp) { // 增加文件打开失败判断 perror("fopen load failed"); return; } // 读取经纬度 fread(&d->lat, sizeof(double), 1, fp); fread(&d->lng, sizeof(double), 1, fp); // 读取字符串长度,分配内存后读取内容 size_t name_len; fread(&name_len, sizeof(size_t), 1, fp); d->name = malloc(name_len + 1); if (!d->name) { perror("malloc failed"); fclose(fp); return; } fread(d->name, name_len, 1, fp); d->name[name_len] = '\0'; // 添加字符串终止符 fclose(fp); } int main(int argc, char **argv) { if(argc != 2) return 1; char *fn = argv[1]; dino d0; d0.lat = 51.083332; d0.lng = -1.166667; // 为name分配内存并赋值 const char *dino_name = "Aves indet."; d0.name = malloc(strlen(dino_name) + 1); if (!d0.name) { perror("malloc d0 failed"); return 1; } strcpy(d0.name, dino_name); save_dino(&d0, fn); dino d1; load_dino(&d1, fn); printf("d1.lat %f\n", d1.lat); printf("d1.lng %f\n", d1.lng); printf("d1.name %s\n", d1.name); // 释放内存,避免泄漏 free(d0.name); free(d1.name); return 0; }
内容的提问来源于stack exchange,提问作者moxhi
相关产品推荐
相关产品推荐

