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

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;
}

关键改进点说明

  1. 减少全局变量:把二维数组和行列数放到局部,通过参数传递,避免全局变量带来的意外问题。
  2. 正确的行列索引:每读一行,行索引row_count递增;每读一个token,列索引current_col递增,确保数据正确存入二维数组对应位置。
  3. 处理换行符:用strlen检查行尾的\n并替换为\0,避免atoi解析错误。
  4. 明确的错误处理:ReadCSV函数返回0表示成功,-1表示失败,更符合C语言的错误处理习惯。
  5. 封装统计函数:sum_column和average_column直接接收二维数组、行数和列索引,就能计算对应列的统计值,完美解决你访问列的需求。

额外注意事项

  • 如果你的CSV包含表头(第一行是字符串不是数字),可以在ReadCSV的while循环前先调用一次fgets跳过第一行,再开始解析数据。
  • 如果CSV里有非整数的数据,atoi会返回0,这时候可以改用strtod处理浮点数,同时把二维数组改成double类型。

内容的提问来源于stack exchange,提问作者Abdelmalek Boughris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 08:42:29