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

如何修复迷宫导航程序嵌套循环中的段错误?

问题

开发了一个迷宫导航程序,定位老鼠的环节出现问题。通过指针数组查找迷宫中代表老鼠的'M'的嵌套循环持续触发段错误,错误发生在if (maze[i][j] == 'M')行。

相关代码片段:

void iterative_search(char **maze, int rows, int cols, char *directions) {
    int x = -1, y = -1;

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (maze[i][j] == 'M') { //<- 段错误发生在此处
                break;
            }
        }
        if (maze[x][y] == 'M') {
            break;
        }
    }
    
    if (x == rows && y == cols) {
        printf("Error: Jerry not found in the maze.\n");
        return;
    }
    // 后续移动逻辑...
}

完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void iterative_search(char **maze, int rows, int cols, char *directions);

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Error: Please provide two input files via command line arguments.\n");
        return 1;
    }

    FILE *maze_file = fopen(argv[1], "r");
    FILE *directions_file = fopen(argv[2], "r");

    if (!maze_file || !directions_file) {
        printf("Error: Could not open input files.\n");
        return 1;
    }

    int rows, cols;
    // 从文件读取迷宫并存储到二维数组
    fscanf(maze_file, "%d %d", &rows, &cols);
    fgetc(maze_file); // 读取行列数后的换行符

    char **maze = malloc(rows * sizeof(char *));
        for (int i = 0; i < rows; i++) {
        maze[i] = malloc((cols + 1) * sizeof(char));
        fgets(maze[i], cols + 1, maze_file);
    }
    fclose(maze_file);


    char *directions = NULL;
    size_t len = 0;
    ssize_t read;

    while ((read = getline(&directions, &len, directions_file)) != -1) {
        iterative_search(maze, rows, cols, directions);
    }
    fclose(directions_file);


    // 将迭代搜索结果写入文件
    FILE *iterative_output = fopen("iterative_output.out", "w");
    if (iterative_output) {
        for (int i = 0; i < rows; i++) {
            fprintf(iterative_output, "%s", maze[i]);
        }
        fclose(iterative_output);
    } else {
        printf("Error: Could not create iterative_output.out file.\n");
    }

    
    // 释放动态分配的内存并关闭文件
    for (int i = 0; i < rows; i++) {
        free(maze[i]);
    }
    free(maze);

    return 0;
}
问题分析与修复方案

核心错误点

  • 未记录'M'的坐标:找到'M'后仅终止内层循环,但未将当前的i和j赋值给x、y,后续执行maze[x][y]时,x和y还是初始值-1,访问非法内存直接触发段错误。
  • 错误的终止判断逻辑:查找结束后判断x == rows && y == cols完全不合理,x和y的合法范围是0~rows-1、0~cols-1,这个条件永远不会成立,无法正确检测'M'未找到的情况。
  • 嵌套循环未完全终止:找到'M'后内层循环终止,但外层循环仍会继续执行,做无用功。

修复后的iterative_search函数

void iterative_search(char **maze, int rows, int cols, char *directions) {
    int x = -1, y = -1;

    // 查找老鼠'M'的位置
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            if (maze[i][j] == 'M') {
                x = i;
                y = j;
                goto found; // 找到后直接跳出所有循环
            }
        }
    }
found:
    // 判断是否找到'M'
    if (x == -1 || y == -1) {
        printf("Error: Jerry not found in the maze.\n");
        return;
    }

    // 执行移动逻辑
    for (int i = 0; directions[i] != '\0'; i++) {
        // 跳过换行符(getline读取的行包含末尾的'\n')
        if (directions[i] == '\n') continue;
        
        int new_x = x;
        int new_y = y;
        switch (directions[i]) {
        case 'N':
            new_x--;
            break;
        case 'E':
            new_y++;
            break;
        case 'S':
            new_x++;
            break;
        case 'W':
            new_y--;
            break;
        default:
            continue;
        }
    
        // 检查新位置是否合法
        if (new_x >= 0 && new_y >= 0 && new_x < rows && new_y < cols &&
            (maze[new_x][new_y] == ' ' || maze[new_x][new_y] == 'C')) {
            // 标记走过的路径(初始位置'M'保留)
            if (maze[x][y] != 'M') {
                maze[x][y] = '.';
            }
            x = new_x;
            y = new_y;
            // 检查是否找到奶酪
            if (maze[x][y] == 'C') {
                printf("Jerry found the cheese at (%d, %d)!\n", x, y);
                break;
            }
        }
    }
}

额外优化点

  • 处理了directions中的换行符:getline会读取到行末尾的\n,跳过该字符避免无效移动指令。
  • 使用goto直接跳出嵌套循环,在这种场景下比多层break更清晰高效。
  • 修正了'M'未找到的判断逻辑,改为检测x或y是否仍为初始值-1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 01:22:07