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

C语言读取CSV异常:可读取Mac格式,无法读取MS-DOS格式

解决CSV读取崩溃问题(CRLF格式)

问题根源分析

  • 仅读取一行数据:你只调用了一次fgets(data,1500,fp),仅将文件第一行读入data数组,后续strtok处理的都是这一行的内容。当第一行所有token处理完毕后,strtok返回NULL,后续调用strtok(NULL, ...)仍返回NULL,传给atof(NULL)会触发空指针访问错误,导致程序崩溃(返回值-1073741819对应Windows系统的0xC0000005空指针异常)。
  • feof循环逻辑错误:feof(fp)仅在读取操作失败后才会置位,你用它作为循环条件且循环内未读取新内容,会导致逻辑混乱。
  • 换行符处理不当:文本模式下打开文件时,C标准库会自动将Windows的CRLF(\r\n)转换为LF(\n),无需同时处理\r和\n。
  • 缺少文件打开校验:若fopen失败返回NULL,后续fgets操作会直接崩溃。

修正后的代码

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

int calculator()
{
    FILE *fp;
    char data[1500];
    
    // 检查文件是否成功打开
    fp = fopen("data.csv", "r");
    if (fp == NULL) {
        perror("无法打开文件");
        return 1;
    }

    char *token;
    int nummer = 1;
    int counterCat = 1;
    int maxCat = 4;

    float buffer_tf = 0;
    float buffer_na = 0;
    float buffer_dh = 0;

    // 读取并处理标题行
    if (fgets(data, 1500, fp) == NULL) {
        fclose(fp);
        return 1;
    }
    printf("\n\n 所有标题:%s", data);

    token = strtok(data, ";");
    printf("\n%i. %s", nummer, token);

    while (counterCat != maxCat) {
        token = strtok(NULL, ";");
        nummer++;
        printf("\n%i. %s", nummer, token);
        counterCat++;
    }

    nummer = 1;
    // 逐行读取并处理数据
    while (fgets(data, 1500, fp) != NULL) {
        printf("\n\n\n 开始处理第 %i 组数据:\n\n", nummer);
        nummer++;

        // 处理第一列(名称)
        token = strtok(data, ";\n");
        if (token == NULL) continue;
        printf("%s\n", token);

        // 处理第二列数值
        token = strtok(NULL, ";\n");
        if (token == NULL) continue;
        printf("%s\n", token);
        buffer_tf = atof(token);
        printf("bt=%f\n", buffer_tf);

        // 处理第三列数值
        token = strtok(NULL, ";\n");
        if (token == NULL) continue;
        buffer_na = atof(token);
        printf("%s\n", token);
        printf("bt=%f\n", buffer_na);

        // 处理第四列数值
        token = strtok(NULL, ";\n");
        if (token == NULL) continue;
        buffer_dh = atof(token);
        printf("bt=%f\n", buffer_dh);

        printf("\n\n 处理结束");
    }

    fclose(fp);
    return 0;
}

关键修正点

  1. 每次循环调用fgets读取一行数据,确保处理文件的每一行内容。
  2. 用";\n"作为strtok分隔符,同时处理分号和换行符,避免残留换行干扰。
  3. 增加文件打开、读取失败的校验,避免空指针访问。
  4. 每次调用strtok后检查返回值,防止后续函数传入空指针。
  5. 移除错误的strtok跳转逻辑,改为逐行处理,逻辑更清晰。

内容的提问来源于stack exchange,提问作者nicht hier 8D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:02:03