C语言读取多行CSV文件示例请求:已实现单行读取
实现C语言多行CSV文件读取的完整示例
Hey! 很高兴你已经搞定了单行CSV的读取,要扩展到多行其实核心就是在单行解析逻辑外层加一个循环,持续读取直到文件末尾。不过有个容易踩坑的点:CSV标准里允许带引号的字段包含换行符,所以不能简单地按换行来分割行,得处理这种特殊场景。下面我给你一个兼顾普通情况和复杂字段的完整实现示例。
测试用CSV输入样例
id,name,description,price 1,"Alice Smith","Software Engineer, loves coding and hiking",5000 2,"Bob Johnson","Product Manager",6500 3,"Charlie Brown","Designer, works remotely from Paris",4800
完整的多行CSV读取实现代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAX_FIELD_LEN 256 #define MAX_FIELDS_PER_LINE 10 // 解析单行CSV(支持字段内换行的场景) int parse_csv_line(FILE *fp, char fields[][MAX_FIELD_LEN], int max_fields) { int field_idx = 0; int in_quotes = 0; char c; char current_field[MAX_FIELD_LEN] = {0}; int current_pos = 0; while ((c = fgetc(fp)) != EOF) { // 处理引号切换:进入/退出引号包裹状态 if (c == '"') { in_quotes = !in_quotes; // 处理CSV里的转义引号:两个连续引号表示一个实际引号 if ((c = fgetc(fp)) == '"' && in_quotes) { if (current_pos < MAX_FIELD_LEN - 1) { current_field[current_pos++] = '"'; } continue; } ungetc(c, fp); // 把非转义的字符放回输入流 continue; } // 非引号状态下,逗号作为字段分隔符 if (!in_quotes && c == ',') { if (field_idx >= max_fields) { fprintf(stderr, "警告:第%d个字段超过最大限制%d,截断处理\n", field_idx+1, max_fields); break; } strncpy(fields[field_idx++], current_field, MAX_FIELD_LEN - 1); memset(current_field, 0, sizeof(current_field)); current_pos = 0; continue; } // 非引号状态下,换行符表示当前行结束 if (!in_quotes && (c == '\n' || c == '\r')) { // 兼容Windows的\r\n换行格式 if (c == '\r') { char next_c = fgetc(fp); if (next_c != '\n') ungetc(next_c, fp); } // 把最后一个字段存入数组 if (current_pos > 0 && field_idx < max_fields) { strncpy(fields[field_idx++], current_field, MAX_FIELD_LEN - 1); } return field_idx; // 返回当前行的字段数量 } // 普通字符加入当前字段,避免溢出 if (current_pos < MAX_FIELD_LEN - 1) { current_field[current_pos++] = c; } else { fprintf(stderr, "警告:字段长度超过最大限制%d,截断处理\n", MAX_FIELD_LEN); } } // 文件结束时,处理最后一行的剩余字段 if (current_pos > 0 && field_idx < max_fields) { strncpy(fields[field_idx++], current_field, MAX_FIELD_LEN - 1); } return field_idx; // 返回最后一行字段数,0表示文件读取完毕 } // 读取多行CSV的主逻辑 int main() { FILE *fp = fopen("data.csv", "r"); if (!fp) { perror("无法打开CSV文件"); return 1; } char fields[MAX_FIELDS_PER_LINE][MAX_FIELD_LEN]; int field_count; int line_num = 0; printf("CSV文件内容如下:\n"); // 循环读取每一行,直到文件结束 while ((field_count = parse_csv_line(fp, fields, MAX_FIELDS_PER_LINE)) > 0) { line_num++; printf("第%d行(共%d个字段):\n", line_num, field_count); for (int i = 0; i < field_count; i++) { printf(" 字段%d: %s\n", i+1, fields[i]); } printf("-------------------------\n"); } fclose(fp); return 0; }
代码关键点说明
- 字段内换行处理:通过
in_quotes标记位判断是否处于引号包裹状态,如果是,遇到换行符不会结束当前行,而是继续读取直到匹配到闭合引号。 - 转义引号处理:CSV标准中两个连续引号表示字段内的一个实际引号,代码会自动识别并转换为单个引号存入字段。
- 循环读取逻辑:主函数通过
while循环反复调用解析函数,直到返回0(表示文件读取完毕)。 - 边界安全:设置了字段长度和每行最大字段数的限制,避免内存溢出,同时会输出警告提示异常情况。
内容的提问来源于stack exchange,提问作者Neios Flame Stuxnet
相关产品推荐
相关产品推荐

