C语言读取CSV存入二维数组后无法正确访问值的问题求助
问题:C语言二维数组访问异常与随机分配逻辑错误
我是C语言初学者,正在完成一个学校项目:将家庭分配到节日的不同日期,分配需满足人数等约束条件。我们有指定格式的CSV文件,为实现分配函数、约束及目标函数,我将CSV数据存入名为matrix的二维数组,以获取每个家庭的人数和日期偏好,并实现了read_csv_file函数(不存储表头)。但遇到两个问题:
- 无法正确访问二维数组的值,在
choose_random_numbers函数中打印matrix[5][~]时,每次输出的数值都不一样 - 实现从家庭偏好中随机选日期的
choose_random_numbers函数时,有时会分配不在偏好中的日期
CSV数据示例
family_size;preference1;preference2;preference3;preference4;preference5 3; 6; 4; 3; 2; 0 3; 3; 1; 0; 2; 4 4; 3; 2; 0; 6; 4 3; 4; 5; 1; 0; 3 8; 2; 0; 5; 1; 6 5; 1; 0; 4; 6; 2
相关代码
读取CSV文件的函数
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <float.h> #define MAX_LINE_LENGTH 1000 #define MAX_NUM_VALUES 6 int read_csv_file(char *filename, int matrix[][MAX_NUM_VALUES], int *num_rows) { FILE *fp; char line[MAX_LINE_LENGTH]; int row = 0, col = 0; // open the file for reading fp = fopen(filename, "r"); if (fp == NULL) { printf("Error opening file %s\n", filename); return 0; } // count the number of rows in the file while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) { (*num_rows)++; } // reset file pointer to the beginning of the file fseek(fp, 0, SEEK_SET); // ignore the first line of the file fgets(line, MAX_LINE_LENGTH, fp); // store the values from the file into the matrix while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) { char *token = strtok(line, ";"); col = 0; while (token != NULL && col < MAX_NUM_VALUES) { matrix[row][col++] = atoi(token); token = strtok(NULL, ";"); } row++; } // close the file fclose(fp); return 1; }
随机分配日期的函数
void choose_random_numbers(int matrix[][MAX_NUM_VALUES], int num_rows, int *random_numbers, int *count_days) { int satisfied = 0; srand(time(NULL)); while (!satisfied) { // Reset count_days to zero memset(count_days, 0, sizeof(int)*7); for (int i = 0; i < num_rows; i++) { // choose random index from 1 to 5 int rand_index = rand() % (MAX_NUM_VALUES - 1) + 1; int day = matrix[i][rand_index]; random_numbers[i] = day; for (int j = 1; j < 6; j++) { if (day == matrix[i][j]) { satisfied = 1; } else{ satisfied = 0; } } count_days[day]+=matrix[i][0]; } satisfied = 1; printf("test: %d", matrix[5][2]); }
主函数
int main() { char *filename = "pb40.csv"; int num_rows = 0; int matrix[MAX_LINE_LENGTH][MAX_NUM_VALUES]; if (!read_csv_file(filename, matrix, &num_rows)) { return 1; } int random_numbers[MAX_NUM_VALUES]; int count_days[7]; choose_random_numbers(matrix, num_rows, random_numbers, count_days); return 0; }
问题原因及修复方案
1. 二维数组访问异常(matrix[5][~]值不稳定)
- 原因:
read_csv_file统计行数时包含了表头,导致num_rows值为总行数(表头+数据行),但后续实际只读取了num_rows-1行数据。主函数中random_numbers数组大小为MAX_NUM_VALUES,当数据行数量超过这个值时,会触发数组越界,破坏matrix的内存空间,导致读取值异常。另外choose_random_numbers末尾强制设置satisfied=1,会让循环提前终止,但越界操作已经造成内存损坏。 - 修复:
- 修改行数统计逻辑,跳过表头再统计数据行:
// 先读取表头,再统计数据行 fgets(line, MAX_LINE_LENGTH, fp); while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) { (*num_rows)++; } fseek(fp, 0, SEEK_SET); fgets(line, MAX_LINE_LENGTH, fp); // 再次跳过表头准备读取数据 - 主函数中
random_numbers的大小应匹配实际数据行数:int random_numbers[num_rows]; // 使用变长数组,或用malloc动态分配内存
- 修改行数统计逻辑,跳过表头再统计数据行:
2. 随机分配不在偏好中的日期
- 原因:日期合法性检查的循环逻辑错误,循环会遍历所有5个偏好项,最后一次比较的结果会覆盖
satisfied的值——即使day是合法偏好,只要最后一个偏好不匹配,satisfied会被设为0,导致错误判断。另外内存越界也会导致matrix中存储的偏好值异常。 - 修复:
- 修改合法性检查逻辑,找到匹配项后立即终止循环:
satisfied = 0; // 初始化为不合法 for (int j = 1; j < 6; j++) { if (day == matrix[i][j]) { satisfied = 1; break; // 找到匹配直接退出循环 } } // 如果不合法,重新处理当前家庭 if (!satisfied) { i--; continue; } - 删除
choose_random_numbers末尾的satisfied = 1,让循环条件正确判断所有家庭是否都分配了合法日期。
- 修改合法性检查逻辑,找到匹配项后立即终止循环:
其他潜在问题修复
- 将
srand(time(NULL))移到主函数中,避免每次循环重新初始化随机数生成器,导致随机数重复。 - 确保日期范围在0-6之间,避免
count_days数组越界。
内容的提问来源于stack exchange,提问作者Raphael42
相关产品推荐
相关产品推荐

