C语言fscanf读取CSV文件遇连续逗号时的异常问题求助
解决C语言fscanf读取CSV连续逗号空值的异常问题
这个问题我之前帮朋友排查过,核心原因就是fscanf默认的行为处理不了CSV里的空字段(连续逗号),导致读取位置错位,把后面的字段读错了地方。
为什么会出错?
举个例子,假设你用类似这样的代码读取CSV:
char col1[20], col2[20]; char flag; fscanf(fp, "%s,%s,%c", col1, col2, &flag);
当遇到abc,,Y这样的行时,第一个%s会读取abc,然后跳过逗号;接下来的%s需要读取非空白字符,但下一个字符是逗号,%s匹配失败,fscanf会停在这个逗号的位置。之后的%c就会直接读取这个逗号,而不是后面的Y——后续的所有读取都会因为这次错位,把本来属于其他字段的内容读进来,就出现了你看到的本该输出Y/N却变成s的情况。
两种可靠的解决方案
方案1:逐字符手动解析(最稳妥,适配更多CSV场景)
放弃fscanf,改用fgetc逐字符读取,手动处理每个字段和分隔符,这样能精准识别空字段:
#include <stdio.h> #include <string.h> #define MAX_FIELD_LEN 100 int main() { FILE *fp = fopen("your_file.csv", "r"); if (!fp) { perror("Failed to open file"); return 1; } char field_buf[MAX_FIELD_LEN]; int buf_idx = 0; int current_char; while ((current_char = fgetc(fp)) != EOF) { // 遇到分隔符(逗号或换行),处理当前字段 if (current_char == ',' || current_char == '\n') { field_buf[buf_idx] = '\0'; // 空字段(buf_idx为0)和非空字段分别处理 if (buf_idx == 0) { printf("(空字段) "); } else { printf("%s ", field_buf); } buf_idx = 0; // 重置缓冲区索引 if (current_char == '\n') printf("\n"); // 换行输出 } else { // 把字符存入缓冲区,避免溢出 if (buf_idx < MAX_FIELD_LEN - 1) { field_buf[buf_idx++] = current_char; } } } // 处理文件末尾未换行的最后一个字段 if (buf_idx > 0) { field_buf[buf_idx] = '\0'; printf("%s\n", field_buf); } fclose(fp); return 0; }
这种方法不仅能处理连续逗号的空值,后续如果遇到带引号的字段(比如"abc,def",Y),也能很方便地扩展逻辑处理。
方案2:改造fscanf的格式字符串(适合简单CSV场景)
如果一定要用fscanf,可以通过格式字符串匹配空字段的情况,核心是先尝试读取字段内容,失败则判定为空字段,再跳过分隔符:
#include <stdio.h> #define MAX_FIELD_LEN 100 int main() { FILE *fp = fopen("your_file.csv", "r"); if (!fp) { perror("Failed to open file"); return 1; } char field[MAX_FIELD_LEN]; int read_result; while (1) { // 尝试读取直到逗号/换行的内容 read_result = fscanf(fp, "%[^,\n]", field); if (read_result == EOF) break; // 文件结束 if (read_result == 0) { // 读取失败,说明是空字段 printf("(空字段) "); } else { printf("%s ", field); } // 跳过逗号或换行符(*表示只匹配不存储) fscanf(fp, "%*[,|\n]"); // 检查是否到行尾,避免重复处理 int c = fgetc(fp); if (c == '\n') { printf("\n"); } else if (c != EOF) { ungetc(c, fp); // 把多读取的字符放回输入流 } } fclose(fp); return 0; }
额外提醒
如果你的CSV还有更复杂的情况(比如字段含换行、引号包裹逗号),建议直接用成熟的C语言CSV解析库(比如libcsv),避免自己造轮子踩更多坑。
内容的提问来源于stack exchange,提问作者user3529201
相关产品推荐
相关产品推荐

