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

C语言CSV读取技术求助:表头存入header数组并指定格式打印

C语言CSV读取与表头使用问题

需求说明

需要编写C语言程序,读取以下格式的CSV文件:

name,hp,damage
duck,20,5
cat,30,10
giraffe,100,20

并按以下格式输出:

name:duck hp:20 damage:5
name:cat hp:30 damage:10
name:giraffe hp:100 damage:20

要求:必须将CSV的表头(原实际为韩文)存入名为header的数组,打印时必须使用该数组。

现有代码

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

typedef struct {
    char name[1000];
    int hp;
    int damage;
} Monster;

typedef struct {
    char header1[4];
    char header2[2];
    char header3[6];
} Header;
int main() 
{
    FILE* fp = fopen("entityData.csv", "r");
    if (!fp) {
        printf("Error opening file\n");
        return 1;
    }

    Monster monsters[100];
    int num_records = 0;

    char line[100];
    Header headerList[20];

    fgets(headerList, sizeof(headerList), fp); 
    char *hd1, *hd2, *hd3;
    hd1 = strtok(headerList, ",");
    strncpy(monsters[num_records].name, hd1, 20);
    hd2 = strtok(NULL, ",");
    hd3 = strtok(NULL, "\n");
    


    while (fgets(line, sizeof(line), fp))
    {
        char* token = strtok(line, ","); 
        strncpy(monsters[num_records].name, token, 20);

        token = strtok(NULL, ",");
        monsters[num_records].hp = atoi(token);

        token = strtok(NULL, ",");
        monsters[num_records].damage = atoi(token);

        num_records++;
    }

    for (int i = 0; i < num_records; i++) {
        printf("name:%s hp:%d damage:%d\n",
            monsters[i].name, monsters[i].hp, monsters[i].damage);
    }

    fclose(fp);
    return 0;
}

问题分析与修正方案

核心问题

  1. 表头存储结构不合理:固定长度的Header结构体无法适配韩文(UTF-8编码下每个韩文占3字节),容易出现截断或越界。
  2. 表头读取逻辑错误:直接用fgets读取到结构体数组headerList是非法操作,且错误将表头内容存入了第一个Monster的name字段。
  3. 打印未使用表头数组:硬编码了输出前缀,不符合需求。

修正步骤

  1. 改用通用表头存储数组:定义二维字符数组char header[3][100];,足够容纳韩文表头(避免长度限制问题)。
  2. 正确读取表头:先读取表头行到临时字符数组,再用strtok分割后存入header数组。
  3. 修正数据读取逻辑:表头读取后不干扰数据行的存储,确保num_records从0开始正确计数。
  4. 打印时使用表头数组:在printf中直接引用header数组的元素,替换硬编码的前缀。

修正后的完整代码

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

typedef struct {
    char name[1000];
    int hp;
    int damage;
} Monster;

int main() 
{
    FILE* fp = fopen("entityData.csv", "r");
    if (!fp) {
        printf("Error opening file\n");
        return 1;
    }

    Monster monsters[100];
    int num_records = 0;
    char header[3][100]; // 存储3个表头字段,每个字段最多100字符(适配韩文)
    char header_line[100];

    // 读取表头行
    if (fgets(header_line, sizeof(header_line), fp) != NULL) {
        // 分割表头并存入header数组
        char* token = strtok(header_line, ",\n"); // 同时处理逗号和换行符
        if (token != NULL) {
            strncpy(header[0], token, sizeof(header[0]) - 1);
            header[0][sizeof(header[0]) - 1] = '\0'; // 确保字符串终止
        }
        token = strtok(NULL, ",\n");
        if (token != NULL) {
            strncpy(header[1], token, sizeof(header[1]) - 1);
            header[1][sizeof(header[1]) - 1] = '\0';
        }
        token = strtok(NULL, ",\n");
        if (token != NULL) {
            strncpy(header[2], token, sizeof(header[2]) - 1);
            header[2][sizeof(header[2]) - 1] = '\0';
        }
    }

    // 读取数据行
    char line[100];
    while (fgets(line, sizeof(line), fp))
    {
        char* token = strtok(line, ",\n"); 
        if (token != NULL) {
            strncpy(monsters[num_records].name, token, sizeof(monsters[num_records].name) - 1);
            monsters[num_records].name[sizeof(monsters[num_records].name) - 1] = '\0';
        }

        token = strtok(NULL, ",\n");
        if (token != NULL) {
            monsters[num_records].hp = atoi(token);
        }

        token = strtok(NULL, ",\n");
        if (token != NULL) {
            monsters[num_records].damage = atoi(token);
        }

        num_records++;
    }

    // 使用header数组打印结果
    for (int i = 0; i < num_records; i++) {
        printf("%s:%s %s:%d %s:%d\n",
            header[0], monsters[i].name,
            header[1], monsters[i].hp,
            header[2], monsters[i].damage);
    }

    fclose(fp);
    return 0;
}

关键说明

  • 表头数组header[3][100]:每个字段预留100字符空间,完全适配韩文UTF-8编码的存储需求,避免长度不足问题。
  • 分割表头时使用,\n作为分隔符:同时处理逗号和换行符,避免表头字段末尾残留换行符。
  • 所有字符串复制都添加了-1的长度限制,并手动添加终止符:防止缓冲区溢出,保证字符串有效性。
  • 打印时直接引用header数组:完全符合需求,无论表头是英文还是韩文都能正确输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:32:45