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

C语言动态内存分配实现:读取CSV存入info_t结构体数组的方法

C语言解析CSV存入动态结构体数组实现

首先修正原结构体定义的笔误:Char 需改为C语言标准的小写char,否则编译无法通过。

实现思路

  • 结构体数组采用动态扩容方案:初始分配4个元素的空间,存储满后每次扩容为原来的2倍,避免频繁申请内存
  • 逐行读取文件,单行缓存大小设为256字节符合要求
  • 分割单行的三个CSV字段,name字段单独申请动态内存,长度限制为24字节(含结束符)
  • 每一步内存申请都做错误校验,申请失败时主动释放已分配的内存,避免内存泄漏
  • 结构体数组以name字段为NULL作为结束哨兵,方便调用方遍历

完整代码实现

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

// 修正后的结构体定义
typedef struct {
    char *name;
    int age;
    double balance;
} info_t;

// 辅助函数:去除字符串首尾的空白符,适配CSV字段前后有空格的场景
static char* trim(char *str) {
    while(isspace((unsigned char)*str)) str++;
    if(*str == 0) return str;
    char *end = str + strlen(str) - 1;
    while(end > str && isspace((unsigned char)*end)) end--;
    end[1] = '\0';
    return str;
}

void readFile(FILE *file, info_t **arr) {
    // 初始化数组参数:初始容量4,当前元素数0
    int capacity = 4;
    int count = 0;
    *arr = (info_t*)malloc(sizeof(info_t) * capacity);
    if (*arr == NULL) {
        perror("结构体数组内存申请失败");
        return;
    }

    char line_buf[256]; // 单行缓存,符合256字节上限要求
    char field_buf[24]; // 单字段缓存,符合24字节上限要求

    // 逐行读取文件
    while (fgets(line_buf, sizeof(line_buf), file) != NULL) {
        // 跳过空行
        size_t len = strlen(line_buf);
        if (len <= 1) continue;
        // 去掉行尾的换行符
        if (line_buf[len-1] == '\n') line_buf[len-1] = '\0';

        // 扩容判断:当前元素数达到容量的前1位(留最后一位存哨兵)
        if (count >= capacity - 1) {
            capacity *= 2;
            info_t *tmp = (info_t*)realloc(*arr, sizeof(info_t) * capacity);
            if (tmp == NULL) {
                perror("结构体数组扩容失败");
                // 释放已分配的内存避免泄漏
                for (int i = 0; i < count; i++) {
                    free((*arr)[i].name);
                }
                free(*arr);
                *arr = NULL;
                return;
            }
            *arr = tmp;
        }

        // 分割CSV字段,默认分隔符为逗号
        char *name_str = strtok(line_buf, ",");
        char *age_str = strtok(NULL, ",");
        char *balance_str = strtok(NULL, ",");
        // 字段不全则跳过当前行
        if (!name_str || !age_str || !balance_str) continue;

        // 处理name字段:去空白,限制长度24字节,动态分配内存
        name_str = trim(name_str);
        strncpy(field_buf, name_str, sizeof(field_buf)-1);
        field_buf[sizeof(field_buf)-1] = '\0';
        (*arr)[count].name = (char*)malloc(strlen(field_buf) + 1);
        if ((*arr)[count].name == NULL) {
            perror("name字段内存申请失败");
            // 释放已分配内存
            for (int i = 0; i < count; i++) {
                free((*arr)[i].name);
            }
            free(*arr);
            *arr = NULL;
            return;
        }
        strcpy((*arr)[count].name, field_buf);

        // 处理age字段
        (*arr)[count].age = atoi(trim(age_str));
        // 处理balance字段
        (*arr)[count].balance = atof(trim(balance_str));

        count++;
    }

    // 写入结束哨兵
    (*arr)[count].name = NULL;
}

调用与内存释放示例

int main() {
    info_t *info_arr = NULL;
    FILE *fp = fopen("data.csv", "r");
    if (fp == NULL) {
        perror("文件打开失败");
        return 1;
    }

    readFile(fp, &info_arr);
    fclose(fp);

    if (info_arr == NULL) {
        return 1;
    }

    // 遍历使用结构体数组
    for (int i = 0; info_arr[i].name != NULL; i++) {
        printf("姓名:%s,年龄:%d,余额:%.2lf\n", 
            info_arr[i].name, info_arr[i].age, info_arr[i].balance);
    }

    // 释放内存:先释放每个元素的name字段,再释放数组本身
    for (int i = 0; info_arr[i].name != NULL; i++) {
        free(info_arr[i].name);
    }
    free(info_arr);

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:09:00