使用getc将文件读入动态分配二维迷宫数组的异常问题求助
迷宫读取程序问题定位与修改方案
核心问题根源
- 逐字符读取的行边界处理完全错误
原代码通过getc逐字符填充数组时,遇到换行符仅简单跳过,没有停止当前行的读取填充。当某行实际长度短于最大列数时,程序会直接读取下一行的字符填充当前行的剩余空位,造成文件指针错位、行列内容完全混乱。仅当所有行长度与分配的列数完全一致时,才不会出现跨行读取的问题。 - 列数统计逻辑存在边界误差
原代码使用getline统计最大列数时,直接比较包含行尾换行符的行长度,最后统一将最大列数减1。这会对没有行尾换行符的最后一行计算出错,导致分配的列数不足或冗余。 - 内存分配存在冗余
原代码为每个迷宫行分配内存时,写的是malloc(*columns * sizeof(char*)),实际每个单元格是char类型,应该使用sizeof(char),否则会在64位系统上分配8倍于实际需要的内存,造成冗余。 - 逐字符读取方式本身冗余
程序第一遍扫描文件时已经通过getline拿到了所有行的长度信息,第二遍完全没有必要使用低级的getc逐字符手动处理换行,反而引入不必要的出错点。
具体修改方案
- 保留原有逻辑中动态分配内存、初始化迷宫所有单元格为空格的步骤——短行的剩余位置本来就应该以空格填充,符合迷宫显示的预期。
- 修正第一遍统计列数的逻辑:每读到一行,先去掉行尾的换行符,再计算实际内容长度,与记录的最大列数比较取最大值,避免统一减1带来的边界误差。
- 修正内存分配的类型错误,按实际需要的
char大小为每行分配内存。 - 第二遍重新读取文件时,直接复用
getline逐行读取内容,不再使用getc逐字符硬读:- 每次读到一行,先剥离行尾的换行符得到实际内容长度
- 将该行的有效内容按位置拷贝到对应的迷宫行数组中
- 剩余未填充的位置因为已经初始化为空格,无需额外处理
这种方式完全不需要手动判断换行符位置,由getline自动完成行边界识别。
核心修改代码示例
char **get_maze_map(char *argv[], int *rows, int *columns) { FILE *fp = fopen(argv[1], "r"); if (!fp) { fprintf(stderr, "\nCould not open %s", argv[1]); exit(-1); } char *line_buf = NULL; size_t line_buf_size = 0; ssize_t line_size; int line_count = 0; *columns = 0; // 第一遍扫描文件,统计行数和最大列数 while ((line_size = getline(&line_buf, &line_buf_size, fp)) >= 0) { line_count++; // 剥离行尾换行符,计算实际内容长度 if (line_size > 0 && line_buf[line_size - 1] == '\n') { line_size--; } // 更新最大列数 if (line_size > *columns) { *columns = line_size; } } *rows = line_count; // 分配迷宫二维数组 char **maze = malloc(*rows * sizeof(char*)); for (int i = 0; i < *rows; i++){ // 修正原代码的sizeof类型错误 maze[i] = malloc(*columns * sizeof(char)); } // 初始化所有单元格为空格 for (int a = 0; a < *rows; a++) { for (int b = 0; b < *columns; b++) { maze[a][b] = ' '; } } rewind(fp); // 第二遍读取文件内容 for (int i = 0; i < *rows; i++) { ssize_t cur_len = getline(&line_buf, &line_buf_size, fp); if (cur_len < 0) break; // 剥离当前行的换行符 if (cur_len > 0 && line_buf[cur_len - 1] == '\n') { cur_len--; } // 按位置拷贝有效内容,做边界校验避免越界 for (int j = 0; j < cur_len && j < *columns; j++) { maze[i][j] = line_buf[j]; } } free(line_buf); fclose(fp); return maze; }
注意事项
- 内容拷贝时必须加上长度边界判断,避免某行长度超过最大列数时出现数组越界。
- 初始化迷宫数组为空格的步骤不能省略,否则短行的剩余位置会是未初始化的内存垃圾值,打印时会出现乱码。
内容的提问来源于stack exchange,提问作者osung61
相关产品推荐
相关产品推荐

