You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:30:53