You need to enable JavaScript to run this app. 使用getc将文件读入动态分配二维迷宫数组的异常问题求助
优惠活动
大模型
产品
解决方案
定价
更多

使用getc将文件读入动态分配二维迷宫数组的异常问题求助

迷宫读取程序问题定位与修改方案

核心问题根源

  • 逐字符读取的行边界处理完全错误
    原代码通过getc逐字符填充数组时,遇到换行符仅简单跳过,没有停止当前行的读取填充。当某行实际长度短于最大列数时,程序会直接读取下一行的字符填充当前行的剩余空位,造成文件指针错位、行列内容完全混乱。仅当所有行长度与分配的列数完全一致时,才不会出现跨行读取的问题。
  • 列数统计逻辑存在边界误差
    原代码使用getline统计最大列数时,直接比较包含行尾换行符的行长度,最后统一将最大列数减1。这会对没有行尾换行符的最后一行计算出错,导致分配的列数不足或冗余。
  • 内存分配存在冗余
    原代码为每个迷宫行分配内存时,写的是malloc(*columns * sizeof(char*)),实际每个单元格是char类型,应该使用sizeof(char),否则会在64位系统上分配8倍于实际需要的内存,造成冗余。
  • 逐字符读取方式本身冗余
    程序第一遍扫描文件时已经通过getline拿到了所有行的长度信息,第二遍完全没有必要使用低级的getc逐字符手动处理换行,反而引入不必要的出错点。

具体修改方案

  1. 保留原有逻辑中动态分配内存、初始化迷宫所有单元格为空格的步骤——短行的剩余位置本来就应该以空格填充,符合迷宫显示的预期。
  2. 修正第一遍统计列数的逻辑:每读到一行,先去掉行尾的换行符,再计算实际内容长度,与记录的最大列数比较取最大值,避免统一减1带来的边界误差。
  3. 修正内存分配的类型错误,按实际需要的char大小为每行分配内存。
  4. 第二遍重新读取文件时,直接复用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.07 03:54:08