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; }
关键修正点
- 每次循环调用
fgets读取一行数据,确保处理文件的每一行内容。 - 用
";\n"作为strtok分隔符,同时处理分号和换行符,避免残留换行干扰。 - 增加文件打开、读取失败的校验,避免空指针访问。
- 每次调用
strtok后检查返回值,防止后续函数传入空指针。 - 移除错误的
strtok跳转逻辑,改为逐行处理,逻辑更清晰。
内容的提问来源于stack exchange,提问作者nicht hier 8D
相关产品推荐
相关产品推荐

