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

如何在结构体中用malloc动态分配命令行传入的币价与日期数据?

如何在结构体中动态分配日期和价格数组来处理多个CSV加密货币数据

我来帮你解决这个动态内存分配的问题!核心思路是先为每个加密货币的数据定义一个结构体,在读取每个CSV文件时,先获取条目数,再用malloc为日期(字符串数组)和价格(浮点数组)动态分配对应的内存空间,这样就能灵活适配不同文件的条目数量了。

第一步:定义合适的结构体

我们需要一个结构体来存储单种加密货币的所有数据,包括文件名、条目数量,以及动态分配的日期和价格数组:

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

// 定义加密货币数据结构体
typedef struct {
    char filename[50];          // 存储CSV文件名
    int entry_count;            // 条目数量(比如253)
    char **dates;               // 动态分配的日期字符串数组
    double *prices;             // 动态分配的价格数组
} CryptoData;

第二步:处理命令行参数并逐个读取CSV文件

命令行传入的参数是程序名+3个CSV文件名,我们需要遍历这些文件,为每个文件创建对应的CryptoData实例,然后动态分配内存并读取数据:

int main(int argc, char *argv[]) {
    // 检查命令行参数数量是否正确(程序名+3个文件)
    if (argc != 4) {
        fprintf(stderr, "用法: %s <BTC.csv> <NEO.csv> <IOT.csv>\n", argv[0]);
        return 1;
    }

    // 为3种加密货币分配结构体数组内存
    CryptoData *crypto_list = malloc(3 * sizeof(CryptoData));
    if (crypto_list == NULL) {
        perror("malloc分配结构体数组失败");
        return 1;
    }

    // 遍历每个CSV文件
    for (int i = 0; i < 3; i++) {
        const char *filename = argv[i+1];
        strncpy(crypto_list[i].filename, filename, sizeof(crypto_list[i].filename)-1);
        crypto_list[i].filename[sizeof(crypto_list[i].filename)-1] = '\0'; // 确保字符串结束

        FILE *fp = fopen(filename, "r");
        if (fp == NULL) {
            perror("打开文件失败");
            // 这里要注意:如果前面已经分配了内存,需要先释放再退出
            for (int j = 0; j < i; j++) {
                free(crypto_list[j].dates);
                free(crypto_list[j].prices);
            }
            free(crypto_list);
            return 1;
        }

        // 第一步:读取条目数量(假设文件第一行是数字,比如253)
        if (fscanf(fp, "%d", &crypto_list[i].entry_count) != 1) {
            fprintf(stderr, "读取%s的条目数失败\n", filename);
            fclose(fp);
            // 同样要释放已分配的内存
            for (int j = 0; j < i; j++) {
                free(crypto_list[j].dates);
                free(crypto_list[j].prices);
            }
            free(crypto_list);
            return 1;
        }
        // 读取完条目数后,要跳过换行符(因为fscanf不会读取换行)
        fgetc(fp);

        // 第二步:为日期和价格数组动态分配内存
        // 日期是字符串数组,每个元素是一个char*,所以要分配entry_count个char*的空间
        crypto_list[i].dates = malloc(crypto_list[i].entry_count * sizeof(char*));
        if (crypto_list[i].dates == NULL) {
            perror("malloc日期数组失败");
            fclose(fp);
            // 释放已分配的资源
            for (int j = 0; j < i; j++) {
                free(crypto_list[j].dates);
                free(crypto_list[j].prices);
            }
            free(crypto_list);
            return 1;
        }

        // 价格是double数组,直接分配entry_count个double的空间
        crypto_list[i].prices = malloc(crypto_list[i].entry_count * sizeof(double));
        if (crypto_list[i].prices == NULL) {
            perror("malloc价格数组失败");
            free(crypto_list[i].dates); // 先释放已分配的日期数组
            fclose(fp);
            // 释放前面的资源
            for (int j = 0; j < i; j++) {
                free(crypto_list[j].dates);
                free(crypto_list[j].prices);
            }
            free(crypto_list);
            return 1;
        }

        // 第三步:逐行读取日期和价格数据
        char date_buf[20]; // 临时存储日期字符串
        double price;
        for (int k = 0; k < crypto_list[i].entry_count; k++) {
            // 读取CSV行,格式是"MM/DD/YY,price"
            if (fscanf(fp, "%19[^,],%lf", date_buf, &price) != 2) {
                fprintf(stderr, "读取%s的第%d条数据失败\n", filename, k+1);
                // 释放当前文件已分配的内存
                free(crypto_list[i].dates);
                free(crypto_list[i].prices);
                fclose(fp);
                // 释放前面的资源
                for (int j = 0; j < i; j++) {
                    free(crypto_list[j].dates);
                    free(crypto_list[j].prices);
                }
                free(crypto_list);
                return 1;
            }
            // 为当前日期字符串分配内存并复制内容
            crypto_list[i].dates[k] = malloc(strlen(date_buf) + 1);
            if (crypto_list[i].dates[k] == NULL) {
                perror("malloc单个日期字符串失败");
                // 释放当前文件已分配的日期和价格
                for (int m = 0; m < k; m++) {
                    free(crypto_list[i].dates[m]);
                }
                free(crypto_list[i].dates);
                free(crypto_list[i].prices);
                fclose(fp);
                // 释放前面的资源
                for (int j = 0; j < i; j++) {
                    free(crypto_list[j].dates);
                    free(crypto_list[j].prices);
                }
                free(crypto_list);
                return 1;
            }
            strcpy(crypto_list[i].dates[k], date_buf);
            crypto_list[i].prices[k] = price;
        }

        fclose(fp);
        printf("成功读取%s的%d条数据\n", filename, crypto_list[i].entry_count);
    }

    // 这里可以添加使用数据的逻辑,比如打印前几条数据
    printf("\n示例数据输出:\n");
    for (int i = 0; i < 3; i++) {
        printf("%s 第一条数据:日期=%s,价格=%.2lf\n",
               crypto_list[i].filename,
               crypto_list[i].dates[0],
               crypto_list[i].prices[0]);
    }

    // 第四步:释放所有动态分配的内存,避免内存泄漏
    for (int i = 0; i < 3; i++) {
        // 先释放每个日期字符串的内存
        for (int k = 0; k < crypto_list[i].entry_count; k++) {
            free(crypto_list[i].dates[k]);
        }
        // 再释放日期数组和价格数组的内存
        free(crypto_list[i].dates);
        free(crypto_list[i].prices);
    }
    // 最后释放结构体数组的内存
    free(crypto_list);

    return 0;
}

关键要点解释

  • 结构体设计:dates是char**类型,因为每个日期是一个字符串,我们需要先分配一个存储指针的数组,再为每个字符串单独分配内存;prices是double*,直接分配连续的double空间即可。
  • 内存分配顺序:先分配结构体数组,再为每个结构体的日期、价格数组分配内存,最后为每个日期字符串分配内存。
  • 错误处理:每次malloc后都要检查是否分配成功,如果失败要及时释放已经分配的内存,避免内存泄漏。
  • 内存释放顺序:和分配顺序相反,先释放每个日期字符串,再释放日期数组、价格数组,最后释放结构体数组。
  • 命令行参数处理:通过argc和argv获取传入的文件名,确保参数数量正确。

测试注意事项

  • 确保每个CSV文件的第一行是条目数(比如253),之后每行是MM/DD/YY,价格的格式,例如02/20/18,11403.7。
  • 编译时可以用gcc -o a.exe crypto_reader.c,然后运行a.exe BTC.csv NEO.csv IOT.csv。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:48:02