C语言解析CSV文件并实现列统计计算的技术求助
解决CSV解析为二维数组并实现列求和的问题
看起来你在CSV解析和二维数组存储上踩了几个典型的坑,我帮你梳理下问题点,然后给出修复后的方案:
你的代码里的核心问题
- 全局数组的行索引错误:你在
PrintTab里固定用mat[1][j++],这会把所有行的数据都塞到同一行,完全没用到i变量,导致数据重叠,后续根本没法按列访问。 - void函数返回值错误:
ReadTab是void类型,但你写了return 1;,这在C里是不合法的,应该改成输出错误后直接return。 - 硬编码文件名:函数参数里的
FileName[]没用到,直接写死了"DATA.csv",函数复用性很差。 - 换行符未处理:
fgets会把行尾的\n读进来,导致最后一个token可能包含换行符,转成整数时会出错。 - 列数未记录:后续做sum/average需要知道有多少列,你的代码没保存这个信息,没法遍历列。
修复后的完整代码
我调整了代码结构,减少全局变量使用,修正了索引问题,添加了列数记录,同时修复了各种小错误:
#include <stdio.h> #include <string.h> #include <stdlib.h> // 需要atoi的头文件 // 定义最大行数和列数,方便后续调整 #define MAX_ROWS 100 #define MAX_COLS 100 // 读取CSV到二维数组,同时返回实际行数和列数 int ReadCSV(const char* filename, int mat[MAX_ROWS][MAX_COLS], int* row_count, int* col_count) { FILE* in_file; in_file = fopen(filename, "r"); if (in_file == NULL) { perror("Unable to open the file"); return -1; // 返回错误码标识失败 } char line[200]; *row_count = 0; *col_count = 0; while (fgets(line, sizeof(line), in_file) != NULL && *row_count < MAX_ROWS) { // 去掉行尾的换行符,避免干扰token解析 size_t len = strlen(line); if (len > 0 && line[len-1] == '\n') { line[len-1] = '\0'; } char* token = strtok(line, ";"); int current_col = 0; while (token != NULL && current_col < MAX_COLS) { // 把字符串转成整数存入数组对应位置 mat[*row_count][current_col] = atoi(token); current_col++; token = strtok(NULL, ";"); } // 记录列数(假设所有行列数一致) if (*row_count == 0) { *col_count = current_col; } (*row_count)++; } fclose(in_file); return 0; // 成功返回0 } // 计算指定列的和 int sum_column(int mat[MAX_ROWS][MAX_COLS], int row_count, int col_index) { if (col_index < 0 || col_index >= MAX_COLS) { printf("Invalid column index\n"); return 0; } int total = 0; for (int i = 0; i < row_count; i++) { total += mat[i][col_index]; } return total; } // 计算指定列的平均值 double average_column(int mat[MAX_ROWS][MAX_COLS], int row_count, int col_index) { int sum = sum_column(mat, row_count, col_index); return (double)sum / row_count; } // 测试用的主函数 int main() { int data[MAX_ROWS][MAX_COLS]; int rows, cols; if (ReadCSV("DATA.csv", data, &rows, &cols) == -1) { return 1; } // 打印数组验证解析结果 printf("Parsed CSV data:\n"); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { printf("%d\t", data[i][j]); } printf("\n"); } // 计算第0列的和与平均值(数组索引从0开始) int col_to_calculate = 0; int sum = sum_column(data, rows, col_to_calculate); double avg = average_column(data, rows, col_to_calculate); printf("\nColumn %d sum: %d\n", col_to_calculate, sum); printf("Column %d average: %.2f\n", col_to_calculate, avg); return 0; }
关键改进点说明
- 减少全局变量:把二维数组和行列数放到局部,通过参数传递,避免全局变量带来的意外问题。
- 正确的行列索引:每读一行,行索引
row_count递增;每读一个token,列索引current_col递增,确保数据正确存入二维数组对应位置。 - 处理换行符:用
strlen检查行尾的\n并替换为\0,避免atoi解析错误。 - 明确的错误处理:
ReadCSV函数返回0表示成功,-1表示失败,更符合C语言的错误处理习惯。 - 封装统计函数:
sum_column和average_column直接接收二维数组、行数和列索引,就能计算对应列的统计值,完美解决你访问列的需求。
额外注意事项
- 如果你的CSV包含表头(第一行是字符串不是数字),可以在
ReadCSV的while循环前先调用一次fgets跳过第一行,再开始解析数据。 - 如果CSV里有非整数的数据,
atoi会返回0,这时候可以改用strtod处理浮点数,同时把二维数组改成double类型。
内容的提问来源于stack exchange,提问作者Abdelmalek Boughris
相关产品推荐
相关产品推荐

