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

如何用fwrite()结合结构体指针写入含char指针的结构体到文本文件?

问题原因

你的car结构体里的plate、model等都是char*指针,fwrite写入的是指针本身的内存地址值,不是指针指向的字符串内容。这些地址是程序运行时的临时内存地址,写入文件后就是一堆无意义的二进制数据,所以看起来是乱码;而且每次程序运行时内存地址可能变化,导致乱码内容不同。

修复方案

方案1:改用固定长度字符数组(最简单直接)

把结构体里的char*换成固定大小的char数组,这样结构体里直接存储字符串内容,fwrite就能一次性把整个结构体的实际数据写入文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int numberOfCars;

// 替换char*为固定长度数组,长度根据实际需求调整
typedef struct
{
    char plate[20];
    char model[30];
    char color[20];
    char ownerName[50];
    char problems[100];
    char status[20];
    int year;

} car ;
void writeIntoDatabase(car *);

int main()
{
    car *Cars;
    numberOfCars=2;
    Cars=(car *)calloc(numberOfCars, sizeof(car));

    int i=0;
    // 使用strcpy复制字符串到数组
    strcpy((Cars+i)->plate, "CJ23YOU");
    strcpy((Cars+i)->model, "Mazda");
    strcpy((Cars+i)->color, "Black");
    strcpy((Cars+i)->ownerName, "Makro_And");
    strcpy((Cars+i)->problems, "Rattling_noise");
    strcpy((Cars+i)->status, "Fixed");
    (Cars+i)->year=2019;
    i++;
    strcpy((Cars+i)->plate, "CJ65YOM");
    strcpy((Cars+i)->model, "Volkswagen");
    strcpy((Cars+i)->color, "White");
    strcpy((Cars+i)->ownerName, "Mars Andy");
    strcpy((Cars+i)->problems, "Rattling noise lllas");
    strcpy((Cars+i)->status, "Pending");
    (Cars+i)->year=2009;

    writeIntoDatabase(Cars);
    printf("%s", (Cars+i)->plate);
    // 记得释放内存
    free(Cars);
    return 0;
}

void writeIntoDatabase(car *Cars)
{
    FILE *DB_ptr=fopen("carsDBwrite.txt","w");
    if(DB_ptr == NULL){ // 增加文件打开失败判断
        perror("Failed to open file");
        return;
    }
    fwrite(Cars,sizeof(car),numberOfCars,DB_ptr);
    fclose(DB_ptr);
}

方案2:手动序列化指针指向的内容(保留指针的灵活性)

如果必须用char*动态分配内存,需要手动把每个字符串的内容写入文件,而不是直接写结构体。可以先写入字符串的长度,再写入字符串内容,这样后续读取时能准确还原:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int numberOfCars;

typedef struct
{
    char *plate;
    char *model;
    char *color;
    char *ownerName;
    char *problems;
    char *status;
    int year;

} car ;
void writeIntoDatabase(car *);

int main()
{
    car *Cars;
    numberOfCars=2;
    Cars=(car *)calloc(numberOfCars, sizeof(car));

    int i=0;
    // 用strdup分配内存并复制字符串,避免指向只读常量区
    (Cars+i)->plate=strdup("CJ23YOU");
    (Cars+i)->model=strdup("Mazda");
    (Cars+i)->color=strdup("Black");
    (Cars+i)->ownerName=strdup("Makro_And");
    (Cars+i)->problems=strdup("Rattling_noise");
    (Cars+i)->status=strdup("Fixed");
    (Cars+i)->year=2019;
    i++;
    (Cars+i)->plate=strdup("CJ65YOM");
    (Cars+i)->model=strdup("Volkswagen");
    (Cars+i)->color=strdup("White");
    (Cars+i)->ownerName=strdup("Mars Andy");
    (Cars+i)->problems=strdup("Rattling noise lllas");
    (Cars+i)->status=strdup("Pending");
    (Cars+i)->year=2009;

    writeIntoDatabase(Cars);
    printf("%s", (Cars+i)->plate);
    
    // 释放每个字符串的内存
    for(int j=0;j<numberOfCars;j++){
        free((Cars+j)->plate);
        free((Cars+j)->model);
        free((Cars+j)->color);
        free((Cars+j)->ownerName);
        free((Cars+j)->problems);
        free((Cars+j)->status);
    }
    free(Cars);
    return 0;
}

void writeIntoDatabase(car *Cars)
{
    FILE *DB_ptr=fopen("carsDBwrite.txt","wb"); // 用二进制模式写入更可靠
    if(DB_ptr == NULL){
        perror("Failed to open file");
        return;
    }

    // 先写入车辆数量
    fwrite(&numberOfCars, sizeof(int), 1, DB_ptr);

    for(int i=0;i<numberOfCars;i++){
        car *current = Cars + i;
        // 写入每个字符串:先写长度,再写内容
        size_t len = strlen(current->plate);
        fwrite(&len, sizeof(size_t), 1, DB_ptr);
        fwrite(current->plate, sizeof(char), len, DB_ptr);

        len = strlen(current->model);
        fwrite(&len, sizeof(size_t), 1, DB_ptr);
        fwrite(current->model, sizeof(char), len, DB_ptr);

        len = strlen(current->color);
        fwrite(&len, sizeof(size_t), 1, DB_ptr);
        fwrite(current->color, sizeof(char), len, DB_ptr);

        len = strlen(current->ownerName);
        fwrite(&len, sizeof(size_t), 1, DB_ptr);
        fwrite(current->ownerName, sizeof(char), len, DB_ptr);

        len = strlen(current->problems);
        fwrite(&len, sizeof(size_t), 1, DB_ptr);
        fwrite(current->problems, sizeof(char), len, DB_ptr);

        len = strlen(current->status);
        fwrite(&len, sizeof(size_t), 1, DB_ptr);
        fwrite(current->status, sizeof(char), len, DB_ptr);

        // 写入年份
        fwrite(&current->year, sizeof(int), 1, DB_ptr);
    }

    fclose(DB_ptr);
}
注意事项
  • 方案1的优点是简单,直接用fwrite/fread即可,但缺点是字符串长度固定,可能浪费内存或不够用。
  • 方案2的优点是灵活,支持任意长度的字符串,但需要手动处理序列化和反序列化,代码更复杂,读取时也要对应先读长度再读内容。
  • 无论哪种方案,都要检查文件是否成功打开,避免空指针操作;使用动态内存后记得释放,防止内存泄漏。

内容的提问来源于stack exchange,提问作者Mikeș

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:50:34