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

C语言读取CSV到结构体数组指针异常问题求助

问题原因分析

你遇到的问题核心是指针指向的内存被重复覆盖:

  • 结构体中的id和day都是字符指针,你直接把strtok返回的指针赋值给它们,但strtok返回的是栈上buffer数组内部的地址。
  • 每次循环执行fgets(buffer, ...)时,都会把新的CSV行内容覆盖buffer里的旧数据。循环结束后,所有结构体的id和day指针都指向同一个buffer区域,自然输出的都是最后一行的内容。

另外你提到试过strcpy但没解决,大概率是因为你没有先给id和day指针分配内存,直接用strcpy往未初始化的指针里写数据,这属于未定义行为,根本无法正确复制内容。

解决方案

需要给每个结构体的id和day单独分配内存,再将strtok解析出的字符串复制到分配好的内存中。有两种常用方式:

方式1:使用strdup(推荐,简化代码)

strdup会自动分配内存并复制字符串(注意:这是POSIX标准函数,大部分编译器和系统都支持):

修改循环内的赋值代码:

// 解析ID
data = strtok(buffer, ",");
sample[counter].id = strdup(data);

// 解析日期,加上\n避免包含换行符
data = strtok(NULL, ",\n");
sample[counter].day = strdup(data);

方式2:手动malloc + strcpy(纯C标准,兼容性更好)

如果需要严格遵循C标准,手动分配内存:

// 解析ID
data = strtok(buffer, ",");
sample[counter].id = malloc(strlen(data) + 1); // +1用于存储字符串结束符'\0'
if (sample[counter].id == NULL) {
    perror("malloc failed");
    exit(EXIT_FAILURE);
}
strcpy(sample[counter].id, data);

// 解析日期
data = strtok(NULL, ",\n");
sample[counter].day = malloc(strlen(data) + 1);
if (sample[counter].day == NULL) {
    perror("malloc failed");
    exit(EXIT_FAILURE);
}
strcpy(sample[counter].day, data);

额外注意事项

  • 解析日期时,strtok的分隔符要加上\n,因为fgets会把行尾的换行符读进buffer,如果不处理,day会包含换行符,输出时可能出现多余空行。
  • 程序结束前要记得释放分配的内存,避免内存泄漏:
for (int i = 0; i < counter; i++) {
    free(sample[i].id);
    free(sample[i].day);
}
修改后的完整代码示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Sample
{
    char *id;
    char *day;
};

int main (){
    struct Sample sample[100];
    char buffer[1000];
    char *data;
    FILE *fp;

    fp = fopen("mwecsv.csv","r");
    if (fp == NULL)
    {
        printf("Cannot open file");
        exit(-1);
    }
    printf("file exists and opened\n");

    // 跳过表头
    fgets(buffer,sizeof(buffer),fp);
    printf("%s\n",buffer);

    int counter = 0;
    while(fgets(buffer,sizeof(buffer),fp)){
        printf("***********\n%s\n******************\n",buffer);
        // 解析ID
        data = strtok(buffer,",");
        printf("first token is %s\n", data);
        sample[counter].id = strdup(data);
        
        // 解析日期,包含\n作为分隔符
        data = strtok(NULL,",\n");
        printf("second token is %s\n", data);
        sample[counter].day= strdup(data);
        counter++;
    }
    fclose(fp);

    // 输出结果
    for (int i = 0; i < counter; i++)
        printf("%s %s\n", sample[i].id, sample[i].day);
    printf("\n");

    // 释放内存
    for (int i = 0; i < counter; i++) {
        free(sample[i].id);
        free(sample[i].day);
    }

    return 0;
}

运行这段代码后,就能得到你期望的输出:

Schd5 Monday
Schd3 Tuesday

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:07:32