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

C语言中fscanf读取CSV文件出错:多词国家名场景问题

问题描述

我正在制作世界杯球队的链表,预加载阶段需要从CSV文件读取数据,但读取包含多词的国家名时出现错误。

示例CSV内容:

Arabia Saudita, Herve, Renard, Salman, C, 0, 1

实际读取输出:

Country:Arabia DT:Saudita Herve Renard Salman C 0 1 Captain: empty Group:Empty 

预期输出:

Country: Arabia Saudita DtName:Herve DtSurname:Renard CaptainName:Salman Group: C

尝试用TXT文件也出现同样问题,因为fscanf会以空格作为分隔符,导致数据错位。以下是出错的代码片段:

FILE *chargue = fopen("Precharge.csv", "r");

while (!feof(charge)) {
    fscanf(charge, "%s", countryAux);
    chargecountry(&team, countryAux);

    fscanf(charge, "%s", nameDTAux);
    fscanf(charge, "%s", surnameDTAux);
    chargenameDT(&team, surnameDTAux, nameDTAux);

    chargeCapitan(&team, nameCapaux);

    fscanf(charge, "%c", &groupAux);
    chargegropu(&team, groupAux);

    fscanf(charge, "%d", &actualscoreaux);
    chargeactualscore(&team, actualscoreaux);

    fscanf(charge, "%d", &faseActualaux);
    chargeFase(&team, faseActualaux);

    insert(lis, team);
    forwards(lis);
}
解决方案

核心问题是fscanf的%s格式符会以**任意空白字符(空格、换行、制表符)**作为字段分隔,但你的CSV是用逗号分隔的,且部分字段(如国家名)包含空格,必须按逗号来分割字段。

方法1:用fgets读取整行,再用strtok分割(推荐)

先读取整行数据到缓冲区,再以, (逗号加空格)作为分隔符拆分每个字段,能正确保留含空格的国家名:

#include <string.h>

// ...

FILE *chargue = fopen("Precharge.csv", "r");
char line[256]; // 假设每行数据不超过256字符

while (fgets(line, sizeof(line), chargue) != NULL) {
    // 去掉换行符
    line[strcspn(line, "\n")] = '\0';

    // 分割字段:注意CSV分隔符是", "(逗号加空格)
    char *token = strtok(line, ", ");
    if (token != NULL) {
        strncpy(countryAux, token, sizeof(countryAux)-1);
        countryAux[sizeof(countryAux)-1] = '\0'; // 确保字符串终止
        chargecountry(&team, countryAux);
    }

    token = strtok(NULL, ", ");
    if (token != NULL) {
        strncpy(nameDTAux, token, sizeof(nameDTAux)-1);
        nameDTAux[sizeof(nameDTAux)-1] = '\0';
    }

    token = strtok(NULL, ", ");
    if (token != NULL) {
        strncpy(surnameDTAux, token, sizeof(surnameDTAux)-1);
        surnameDTAux[sizeof(surnameDTAux)-1] = '\0';
        chargenameDT(&team, surnameDTAux, nameDTAux);
    }

    token = strtok(NULL, ", ");
    if (token != NULL) {
        strncpy(nameCapaux, token, sizeof(nameCapaux)-1);
        nameCapaux[sizeof(nameCapaux)-1] = '\0';
        chargeCapitan(&team, nameCapaux);
    }

    token = strtok(NULL, ", ");
    if (token != NULL) {
        groupAux = token[0]; // 分组是单个字符
        chargegropu(&team, groupAux);
    }

    token = strtok(NULL, ", ");
    if (token != NULL) {
        actualscoreaux = atoi(token);
        chargeactualscore(&team, actualscoreaux);
    }

    token = strtok(NULL, ", ");
    if (token != NULL) {
        faseActualaux = atoi(token);
        chargeFase(&team, faseActualaux);
    }

    insert(lis, team);
    forwards(lis);
}
fclose(chargue);

方法2:用sscanf的自定义格式匹配

如果不想用strtok,可以直接用sscanf指定匹配到逗号前的内容,格式字符串中用%[^,]来匹配任意非逗号字符(包括空格):

FILE *chargue = fopen("Precharge.csv", "r");

// 注意格式中的", ":匹配逗号加空格的分隔符
while (sscanf(chargue, "%[^,], %[^,], %[^,], %[^,], %c, %d, %d", 
              countryAux, nameDTAux, surnameDTAux, nameCapaux, 
              &groupAux, &actualscoreaux, &faseActualaux) == 7) {
    
    chargecountry(&team, countryAux);
    chargenameDT(&team, surnameDTAux, nameDTAux);
    chargeCapitan(&team, nameCapaux);
    chargegropu(&team, groupAux);
    chargeactualscore(&team, actualscoreaux);
    chargeFase(&team, faseActualaux);

    insert(lis, team);
    forwards(lis);

    // 处理换行符(避免下一次读取时残留)
    while (fgetc(chargue) != '\n' && !feof(chargue));
}
fclose(chargue);

注意:%[^,]会读取直到遇到逗号的所有字符,包括空格,刚好适配带空格的国家名;同时要确保每个缓冲区(如countryAux)的大小足够容纳最长的字段内容,避免缓冲区溢出。

额外注意事项

  • 不要用while (!feof(charge)):feof只有在读取到文件末尾后才会触发,会导致最后一行被重复读取,改用fgets或sscanf的返回值判断循环结束更可靠。
  • 缓冲区要留足空间,最好用strncpy代替直接赋值,避免字符串溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:50:24