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

C语言strtok函数处理CSV空值问题求助

问题:使用strtok读取CSV时丢失空字段并触发段错误

CSV测试数据

999999999,AA999999999,20240121,Uimo,Jacob,19910306,,,,,9999999999,Sam,Gok

现有实现代码

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

int main() {
    char *inFile;
    char  line[8192];
    int   rowIndex = 0;
    const char *filename = "TestFile.csv"; // 补充缺失的filename定义

    if ((inFile = fopen(filename, "r")) == NULL)
    {
       printf("Could not open input file [%s]\n", filename);
       return 1;
    }

    // Skip the header line
    fgets(line, sizeof(line) - 1, inFile);

    while (fgets(line, sizeof(line) - 1, inFile) != NULL)
    {  
       char *token = strtok(line, ",");
       int   fieldIndex = 0;

       printf("************** RECORD %d **************\n", rowIndex);

       while(fieldIndex < 13)
       {
         if (strlen(token) == 0)
         {
            token = " "; // 原代码单引号赋值错误,需用双引号字符串
            printf("Field %d: '%s'\n", fieldIndex, token);
         }
         else
         {
            printf("Field %d: '%s'\n", fieldIndex, token);
         }

          token = strtok(NULL, ",");
          fieldIndex++;
       }   

       rowIndex++;
    }

    fclose(inFile);
    return 0;
}

当前错误输出

************** RECORD 0 **************
Field 0: '999999999'
Field 1: 'AA999999999'
Field 2: '20240121'
Field 3: 'Uimo'
Field 4: 'Jacob'
Field 5: '19910306'
Field 6: '9999999999'
Field 7: 'Sam'
Field 8: 'Gok
'
Segmentation fault (core dumped)

期望正确输出

************** RECORD 0 **************
Field 0: '999999999'
Field 1: 'AA999999999'
Field 2: '20240121'
Field 3: 'Uimo'
Field 4: 'Jacob'
Field 5: '19910306'
Field 6: ' '
Field 7: ' '
Field 8: ' '
Field 9: ' '
Field 10: '9999999999'
Field 11: 'Sam'
Field 12: 'Gok'

问题分析与解决方案

核心问题

  1. strtok的局限性:strtok会自动跳过连续分隔符,无法识别两个逗号间的空字段,直接丢失了第6-9位的空值。
  2. 空指针访问错误:所有有效token读取完毕后,token变为NULL,此时调用strlen(token)触发段错误。
  3. 未处理换行符:fgets读取的行包含末尾\n,导致最后一个字段带换行符。

修正方案

放弃strtok,改为手动遍历字符串分割字段,处理空字段与剩余字段填充:

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

int main() {
    FILE *inFile; // 修正文件指针类型,原代码char*错误
    char  line[8192];
    int   rowIndex = 0;
    const char *filename = "TestFile.csv";

    if ((inFile = fopen(filename, "r")) == NULL)
    {
       printf("Could not open input file [%s]\n", filename);
       return 1;
    }

    // Skip the header line
    fgets(line, sizeof(line) - 1, inFile);

    while (fgets(line, sizeof(line) - 1, inFile) != NULL)
    {  
       // 去除行末尾换行符
       size_t len = strlen(line);
       if (len > 0 && line[len-1] == '\n') {
           line[len-1] = '\0';
       }

       char *current = line;
       int   fieldIndex = 0;

       printf("************** RECORD %d **************\n", rowIndex);

       while(fieldIndex < 13)
       {
           char *comma_pos = strchr(current, ',');
           char field[256] = {0};

           if (comma_pos != NULL && comma_pos > current) {
               // 非空字段,复制内容
               strncpy(field, current, comma_pos - current);
               current = comma_pos + 1;
               printf("Field %d: '%s'\n", fieldIndex, field);
           } else if (comma_pos == current) {
               // 空字段(连续逗号)
               printf("Field %d: ' '\n", fieldIndex);
               current = comma_pos + 1;
           } else {
               // 最后一个字段或无更多字段
               if (current != NULL && *current != '\0') {
                   strcpy(field, current);
                   printf("Field %d: '%s'\n", fieldIndex, field);
               } else {
                   // 剩余字段填充空格
                   printf("Field %d: ' '\n", fieldIndex);
               }
               current = NULL; // 标记无更多字段
           }

           fieldIndex++;
       }   

       rowIndex++;
    }

    fclose(inFile);
    return 0;
}

关键修正点

  1. 修正文件指针类型:将char *inFile改为FILE *inFile,符合C标准文件操作要求。
  2. 去除换行符:读取行后立即清除末尾\n,避免字段包含无效换行。
  3. 手动分割字段:用strchr定位逗号,区分空字段、非空字段与末尾字段。
  4. 剩余字段填充:所有字段读取完毕后,剩余位置用空格填充,确保输出13个字段。
  5. 空指针防护:判断current有效性,避免访问空指针触发错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 19:55:19