我正在尝试使用BFS解决迷宫,但是遇到了分段错误。谁能帮我弄清楚为什么会这样吗?另外,如果您发现我的代码还有其他问题吗?我的if语句用于检查迷宫中是否存在该点以及该点是否存在空白。我也正在使用DFS解决迷宫,但是seg错误发生在resolve_bfs期间。而且,除了solve.c之外的所有东西都交给了我的教授,所以我唯一想编辑的就是solve.c
解决。c
#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
#include "stack.h"
#include "queue.h"
int solve_bfs(maze * the_maze){
Queue Q= initQueue();
enqueue(Q, the_maze->entry);
while(!emptyQueue(Q)){
coord to_explore= dequeue(Q);
if(to_explore.row == the_maze->exit.row && to_explore.col == the_maze->exit.col){
print_maze(the_maze);
free(Q);
return 1;
}
else{
the_maze->data[to_explore.row][to_explore.col]= 'o';
if(to_explore.row-1 >= 0){
if(the_maze->data[to_explore.row-1][to_explore.col] == ' '){
coord new;
new.row= to_explore.row-1;
new.col= to_explore.col;
enqueue(Q, new);
}
}
if(to_explore.col+1 < the_maze->width){
if(the_maze->data[to_explore.row][to_explore.col+1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col+1;
enqueue(Q, new);
}
}
if(to_explore.row+1 < the_maze->height){
if(the_maze->data[to_explore.row+1][to_explore.col]== ' '){
coord new;
new.row= to_explore.row+1;
new.col= to_explore.col;
enqueue(Q, new);
}
}
if(to_explore.col-1 >= 0) {
if(the_maze->data[to_explore.row][to_explore.col-1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col-1;
enqueue(Q, new);
}
}
}
if(emptyQueue(Q)){
print_maze(the_maze);
free(Q);
return 0;
}
}
}
int solve_dfs(maze * the_maze){
Stack s= initStack();
push(s, the_maze->entry);
while(!emptyStack(s)){
coord to_explore= pop(s);
if(to_explore.row == the_maze->exit.row && to_explore.col == the_maze->exit.col){
print_maze(the_maze);
free(s);
return 1;
}
else{
if(to_explore.row-1 >= 0){
if(the_maze->data[to_explore.row-1][to_explore.col]== ' '){
coord new;
new.row= to_explore.row-1;
new.col= to_explore.col;
push(s, new);
}
}
if(to_explore.col+1 < the_maze->width){
if(the_maze->data[to_explore.row][to_explore.col+1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col+1;
push(s, new);
}
}
if(to_explore.row+1 < the_maze->height){
if(the_maze->data[to_explore.row+1][to_explore.col]== ' '){
coord new;
new.row= to_explore.row+1;
new.col= to_explore.col;
push(s, new);
}
}
if(to_explore.col-1 >= 0){
if(the_maze->data[to_explore.row][to_explore.col-1]== ' '){
coord new;
new.row= to_explore.row;
new.col= to_explore.col-1;
push(s, new);
}
}
}
if(emptyStack(s)){
print_maze(the_maze);
free(s);
return 0;
}
}
}
void print_maze(maze * the_maze){
the_maze->data[the_maze->entry.row][the_maze->entry.col]='S';
the_maze->data[the_maze->exit.row][the_maze->exit.col]='F';
for(int i=0; i<the_maze->width; i++){
for(int j=0; j<the_maze->height; j++){
printf("%s",the_maze->data[i][j]);
}
}
}
coord * make_coord(int r, int c){
coord * coord= malloc(sizeof(coord));
coord->row = r;
coord->col = c;
return coord;
}
void print_coord(coord c){
printf("(%d,%d)",c.row, c.col);
}
Maze.c
#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
/**********************************************************
create_maze
creates a new maze from the input file characters
*********************************************************/
maze * create_maze(FILE *in) {
// create maze
maze * new_maze = (maze *) malloc(sizeof(maze));
// read first line of in
int start_row;
int start_col;
int end_row;
int end_col;
int num_rows;
int num_cols;
// start line
char * line = malloc(sizeof(char)*100); // start buffer out at 100
size_t num_read;
getline(&line, &num_read, in);
if(sscanf(line, "%d %d %d %d %d %d", &num_rows, &num_cols, &start_row, &start_col, &end_row, &end_col) != 6) {
fprintf(stderr, "Maze file format invalid. Top line must include 6 numbers.\n");
return NULL;
}
// if any are negative values, return NULL
if(start_row < 0 || start_col < 0 || end_row < 0 || end_col < 0 || num_rows < 0 || num_cols < 0) {
fprintf(stderr, "Maze file format invalid. Maze file numbers in first row must be non-negative.\n");
return NULL;
}
// make sure start_row is in bounds
if(start_row >= num_rows) {
fprintf(stderr, "Maze file format invalid. Start row must be < num rows in maze.\n");
return NULL;
}
// make sure end_row is in bounds
if(end_row >= num_rows) {
fprintf(stderr, "Maze file format invalid. End row must be < num rows in maze.\n");
return NULL;
}
// make sure start_col is in bounds
if(start_col >= num_cols) {
fprintf(stderr, "Maze file format invalid. Start col must be < num cols in maze.\n");
return NULL;
}
// make sure end_col is in bounds
if(end_col >= num_cols) {
fprintf(stderr, "Maze file format invalid. Start col must be < num cols in maze.\n");
return NULL;
}
// assign maze members
new_maze->entry.row = start_row;
new_maze->entry.col = start_col;
new_maze->exit.row = end_row;
new_maze->exit.col = end_col;
new_maze->width = num_cols;
new_maze->height = num_rows;
// allocate memory for maze data
new_maze->data = (char **) malloc(sizeof(char *)*num_rows);
int i;
for(i=0; i<num_rows; i++) {
new_maze->data[i] = (char *) malloc(sizeof(char)*num_cols);
}
// get characters from file, one line at a time
size_t num_vals_read = 0;
for(i=0; i<num_rows; i++) {
num_vals_read = getline(&line, &num_read, in);
if(num_vals_read != num_cols + 1) { //account for newline character
fprintf(stderr, "Maze file format invalid. Found %d chars on line %d and the width is %d.\n",
(num_vals_read-1), i, new_maze->width);
return NULL;
}
// parse out line
int j;
for(j=0; j<num_cols; j++) {
if(line[j] != ' ' && line[j] != '*') {
fprintf(stderr, "Maze file format invalid. Maze file data must contain spaces and stars. Read %c.\n", line[j]);
return NULL;
}
new_maze->data[i][j] = line[j];
}
}
// try to read more data
char c;
if((c = fgetc(in)) != EOF) {
fprintf(stderr, "Maze file format invalid. Too many characters past %d rows.\n", num_rows);
return NULL;
}
free(line);
return new_maze;
}
/******************************************************
free_maze
frees memory used by the_maze
******************************************************/
void free_maze(maze * the_maze) {
// first free the data
// need to free rows of data, then data
int i;
for(i = 0; i < the_maze->height; i++) {
free(the_maze->data[i]);
}
free(the_maze->data);
free(the_maze);
return;
}
Queue.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
/* initializes empty queue */
Queue initQueue() {
Queue q = malloc(sizeof(QueueType));
q->head = 0;
q->tail = 0;
return q;
}
/* returns 1 if queue is empty and 0 otherwise */
int emptyQueue(Queue Q) {
return (Q->head == Q->tail);
}
/* puts data item d into queue */
void enqueue(Queue Q, QueueData d) {
if(full(Q)) {
printf("Queue is full. Did not add item.\n");
return;
}
Q->tail++;
Q->tail = Q->tail % MAX_Q; // in case it goes off array
Q->data[Q->tail] = d;
}
/* removes data item from queue */
QueueData dequeue(Queue Q) {
if(emptyQueue(Q)) {
printf("Attempting to remove from empty queue\n");
exit(1);
}
Q->head++;
Q->head = Q->head % MAX_Q; // in case it goes off array
return Q->data[Q->head];
}
/* checks if queue is full */
int full(Queue Q) {
return (Q->tail + 1) % MAX_Q == Q->head;
}
/* freeQueue */
void freeQueue(Queue Q) {
free(Q);
}
Main.c
#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
#define NUM_PARAMS 2
/* prototypes */
void usage(char * executable);
/***********************************************************************
* main
executable_name input_filename.txt
opens input_filename.txt for reading
creates maze object
runs the maze solver
frees maze
*********************************************************************/
// function completed for the CS 305 students: DO NOT MODIFY (Unless you find a bug)
int main(int argc, char * argv[]) {
if(argc != NUM_PARAMS) {
usage(argv[0]);
return EXIT_FAILURE;
}
// open file for reading
FILE *fp = NULL;
fp = fopen(argv[1], "r");
if(fp == NULL) {
fprintf(stderr, "Error opening input file %s. Exiting.\n", argv[1]);
return EXIT_FAILURE;
}
// create maze objects
// need 2 since we are running BFS on one (which modifies the
// maze with the path marker character)
// need clean copy of maze for DFS
maze * the_maze = create_maze(fp);
rewind(fp); // resets file pointer to beginning of file
maze * the_maze2 = create_maze(fp);
// done with file at this point
fclose(fp);
fp = NULL;
// check maze to see if it was created successfully
if(the_maze == NULL || the_maze2 == NULL) {
fprintf(stderr, "Error creating maze data structure\n");
return EXIT_FAILURE;
}
// run breadth-first-search on maze
printf("\nSolving using breadth-first search.\n");
int a = solve_bfs(the_maze);
// run depth-first-search on maze
printf("\nSolving using depth-first search:\n");
int b = solve_dfs(the_maze2);
printf("\ncan solve BFS: %d, can solve DFS: %d\n\n", a, b);
// free memory and exit
free_maze(the_maze);
free_maze(the_maze2);
return EXIT_SUCCESS;
}
/*********************************************************
usage
prints error message to user
**********************************************************/
void usage(char * executable) {
printf("Usage: \n%s maze_file.txt\n", executable);
}
stack.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
/* initializes a new stack */
Stack initStack() {
Stack s = (Stack) malloc(sizeof(StackType));
s->top = NULL;
return s;
}
/* empty returns 0 if S is empty and non-zero if S is not empty */
int emptyStack(Stack S) {
return (S->top == NULL);
}
/* pushes d to S */
void push(Stack S, StackData d) {
Node * n = (Node *)malloc(sizeof(Node));
n->data = d;
n->next = S->top;
S->top = n;
}
/* pops top item from S */
StackData pop(Stack S) {
if(emptyStack(S)) {
printf("Stack is empty. Attempting to pop an empty stack. Exiting program.\n");
exit(1); // exiting program
}
// there is data to pop
StackData toReturn = S->top->data;
Node * tmp = S->top; // in order to free this later
S->top = S->top->next; // move pointer to next item in stack
free(tmp);
return toReturn;
}
/* frees stack memory */
void freeStack(Stack S) {
while(!emptyStack(S)) {
pop(S);
}
free(S);
}
queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include "maze.h"
#define MAX_Q 5000 // 1 more than what can be stored in the queue
// in this application, the mazes are on the small
// side
/* data to store into queue */
typedef coord QueueData; // putting coordinates into queue
/* queue data structure */
typedef struct QueueTag QueueType;
typedef struct QueueTag* Queue; // pointer to queue struct
// so when it is passed, the values
// can be updated in functions
struct QueueTag {
int head;
int tail;
QueueData data[MAX_Q]; // space for items in queue
};
/* function prototypes on queues */
Queue initQueue();
int emptyQueue(Queue Q);
void enqueue(Queue Q, QueueData d);
QueueData dequeue(Queue Q);
int full(Queue Q);
void freeQueue();
#endif
maze.h
#ifndef MAZE_H
#define MAZE_H
/* struct definition for coord */
typedef struct coord {
int row;
int col;
} coord;
/* struct definition for maze */
typedef struct maze {
coord entry;
coord exit;
int width;
int height;
char ** data;
} maze;
/* prototypes */
/* in maze.c */
maze * create_maze(FILE *in);
void free_maze(maze * the_maze);
/* in solve.c */
int solve_bfs(maze * the_maze);
int solve_dfs(maze * the_maze);
void print_maze(maze * the_maze);
coord * make_coord(int r, int c);
void print_coord(coord c);
#endif
stack.h
#ifndef STACK_H
#define STACK_H
#include "maze.h"
#define BAD {-1, -1} // coordinate off maze
/* data to store into stack */
typedef coord StackData;
/* stack data structures */
typedef struct NodeTag Node;
typedef struct StackTag StackType;
typedef struct StackTag* Stack;
/* linked list implementation of stacks */
struct NodeTag {
StackData data;
Node *next;
};
struct StackTag {
Node * top;
};
/* function prototypes on stacks */
Stack initStack();
int emptyStack(Stack S);
void push(Stack S, StackData d);
StackData pop(Stack S);
void freeStack(Stack S);
#endif
答案 0 :(得分:1)
假设索引从零开始,您需要修复边界检查
# incorrect
to_explore.col+1 =< the_maze->width
# correct
to_explore.col+1 < the_maze->width
类似的情况是检查to_explore.row 强调的文本
答案 1 :(得分:1)
错误在print_maze
函数中。
void print_maze(maze * the_maze){
the_maze->data[the_maze->entry.row][the_maze->entry.col]='S';
the_maze->data[the_maze->exit.row][the_maze->exit.col]='F';
for(int i=0; i<the_maze->width; i++){
for(int j=0; j<the_maze->height; j++){
printf("%s",the_maze->data[i][j]);
}
}
data[i]
代表第i
行,因此我应该遍历高度。
data[i][j]
代表j
行中的第ith
个元素,因此j
应该遍历宽度。您需要在for循环中交换高度和宽度。
void print_maze(maze * the_maze){
the_maze->data[the_maze->entry.row][the_maze->entry.col]='S';
the_maze->data[the_maze->exit.row][the_maze->exit.col]='F';
for(int i=0; i<the_maze->height; i++){
for(int j=0; j<the_maze->width; j++){
printf("%s",the_maze->data[i][j]);
}
}
}