debugging 为什么我在这个拼字搜索程序中得到一个分段错误?

htrmnn0y  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(88)

我在searchbogle上有一个分段错误,因为我查找它的东西与字符串路径有关,我认为在main函数。我应该为每次迭代创建一个新的空字符串或空路径来做我想做的事情,但我不能这样做。它应该路径应该是一个字符串当我递归到板我添加更多字符和当我开始一个新的点应该是一个空字符串。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "hash.h"

#define MAX_WORD_LENGTH 30

int wordcount = 0;
int row[] = { -1, -1, -1, 0, 1, 0, 1, 1 };
int col[] = { -1, 1, 0, -1, -1, 1, 0, 1 };

HashTable readwords(HashTable H, char *filename) {
    char word[50] = "";
    FILE *f = fopen(filename, "r");
    while (fscanf(f, " %s", word) != EOF)
        Insert(word, H);
    fclose(f);
    return H;
}

void readboard(char *filename, char board[][4]) {
    FILE *file;
    char line[12];
    // Open the file
    file = fopen(filename, "r");
    if (file == NULL) {
        printf("Error opening the file.\n");
        return;
    }
    int x = 0;
    // Read the file and populate the board dynamically
    while (fgets(line, sizeof(line), file) != NULL && x < 4) {
        board[x][0] = line[0];
        board[x][1] = line[2];
        board[x][2] = line[4];
        board[x][3] = line[6];
        x++;
    }
    // Close the file
    fclose(file);
}

bool isSafe(int x, int y, bool processed[][4]) {
    return (x >= 0 && x < 4) && (y >= 0 && y < 4) && !processed[x][y];
}

void searchBoggle(char board[][4], HashTable words, char answer[200][30],
                  bool processed[][4], int x, int y, char *path,
                  int wordX[30], int wordY[30]) {

    // marca o nó atual como processado
    processed[x][y] = true;
 
    // atualiza o caminho com o caractere atual e o insere no conjunto
    strncat(path, &board[x][y], 1);
 
    // verifica se o caminho está presente no conjunto de entrada
    if (Find(path, words)) {
        wordcount++;
        int sz = strlen(path);
        for (int j = 0; j < sz; j++) {
            answer[wordcount][j] = path[j];
        }
    }
    
    // verifica todos os oito movimentos possíveis da célula atual
    for (int k = 0; k < 8; k++) {
        // pula se uma célula é inválida ou já foi processada
        if (isSafe(x + row[k], y + col[k], processed)) {
            searchBoggle(board, words, answer, processed,
                         x + row[k], y + col[k], path, wordX, wordY);
        }
    }
    
    // backtrack: marca o nó atual como não processado
    processed[x][y] = false;
}

int main() {
    char path[30] = "";
    char filename[] = "corncob_caps_2023.txt";
    char filename2[] = "boggle0.txt"; 
    int tableSize = 60000; 
    char answer[200][30];
    bool processed[4][4];
    int wordX[30];
    int wordY[30];
    char board[4][4];
    HashTable words = InitializeTable(tableSize);
    words = readwords(words, filename);
    
    readboard(filename2, board);
    for (int x = 0; x < 4; x++) {
        for (int y = 0; y < 4; y++) {
            // considera cada caractere como um ponto de partida e executa o DFS
            searchBoggle(board, words, answer, processed, x, y, path, wordX, wordY);
        }
    }
    return 0;
}

如果需要更多的东西,请让我知道,这样我就可以添加了。
看到所有的答案,我改变了代码,知道它看起来像这样,我运行它调试和它accutaly运行只是fin只是需要一些时间,但当我正常运行它只是给我分段错误再次。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "hash.h"

#define MAX_WORD_LENGTH 30
int wordcount=0;
int row[] = { -1, -1, -1, 0, 1, 0, 1, 1 };
int col[] = { -1, 1, 0, -1, -1, 1, 0, 1 };

HashTable readwords(HashTable H,char *filename){
    char word[50]="";
    FILE* f = fopen(filename, "r");
    while(fscanf(f, " %s", word) != EOF)
        Insert(word, H);
    fclose(f);
    return H;
}

HashTable readCharsWords(HashTable H,char *filename){
    char word[50]="";
    int sz;
    FILE* f = fopen(filename, "r");
    while(fscanf(f, " %s", word) != EOF){
        char d[30];
        sz = strlen(word);
        memset(d, 0, sizeof(d));
        for (int j = 0; j < sz-1; j++) {
            d[j]=word[j];
            d[j+1]='\0';
            if(!Find(d,H)){
                Insert(d,H);
            }    
        }
        
    }
    fclose(f);
    return H;
}

void readboard(char *filename,char board[][4]) {
    FILE *file;
    char line[12];
    // Open the file
    file = fopen(filename, "r");
    if (file == NULL) {
        printf("Error opening the file.\n");
        return;
    }
    int x=0;
    // Read the file and populate the board dynamically
    while (fgets(line, sizeof(line), file) != NULL&&x<4) {
        board[x][0] = line[0];
        board[x][1] = line[2];
        board[x][2] = line[4];
        board[x][3] = line[6];
        x++;

    }
    // Close the file
    fclose(file);

    
}
bool isSafe(int x, int y, bool processed[][4]) {
    return (x >= 0 && x < 4) && (y >= 0 && y < 4) &&
        !processed[x][y];
}

void searchBoggle(char board[][4], HashTable halfwords, HashTable words, char answer[200][30], bool processed[][4], int x, int y, char *path, int wordX[30], int wordY[30],int len){
    // marca o nó atual como processado
    processed[x][y] = true;
 
    // atualiza o caminho com o caractere atual e o insere no conjunto
    path[len] = board[x][y]; path[len + 1] = '\0';
 
    // verifica se o caminho está presente no conjunto de entrada
    if (Find(path, words) && wordcount < 200) {
        strcpy(answer[wordcount++], path);
    }
    
    if(!Find(path, halfwords)){
        return;
    }
    
    // verifica todos os oito movimentos possíveis da célula atual
    for (int k = 0; k < 8; k++)
    {
        // pula se uma célula é inválida ou já foi processada
        if (isSafe(x + row[k], y + col[k], processed)) {
            searchBoggle(board, halfwords, words, answer, processed, x + row[k], y + col[k], path,wordX,wordY,len + 1);
        }
    }
    
    // backtrack: marca o nó atual como não processado
    processed[x][y] = false;
}

int main(){
    char path[30]="";
    char filename[] = "corncob_caps_2023.txt";
    char filename2[] = "boggle0.txt"; 
    int tableSize = 60000; 
    HashTable H = InitializeTable(200000);
    H=readCharsWords(H,filename);
    char answer[200][30];
    bool processed[4][4];
    int wordX[30];
    int wordY[30];
    char board[4][4];
    HashTable words = InitializeTable(tableSize);
    words = readwords(words, filename);
    
    readboard(filename2, board);
    for (int x = 0; x < 4; x++){
        for (int y = 0; y < 4; y++) {
            // considera cada caractere como um ponto de partida e executa o DFS
            searchBoggle(board,H,words,answer,processed, x,y, path,wordX,wordY,0);
            
        }
    }
    
    return 0;
}
gab6jxml

gab6jxml1#

以下是代码中可能产生未定义行为的一些问题:

  • readwords中,您不检查fopen()故障,当您使用空指针调用fscanf()时,可能会导致崩溃。
  • fscanf(f, " %s", word)可能会导致缓冲区溢出,如果任何单词从字典是超过49个字母.
  • 此外,您应该比较fscanf()1的返回值,而不是只测试EOF

以下是修改后的版本:

#include <errno.h>

HashTable readwords(HashTable H, char *filename) {
    char word[50] = "";
    FILE *f = fopen(filename, "r");
    if (f == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
        exit(1);
    }
    while (fscanf(f, "%49s", word) == 1) {
        Insert(word, H);
    }
    fclose(f);
    return H;
}
  • 你总是用strncat(path, &board[x][y], 1);将下一个字符追加到path,但从不回溯,导致path最终溢出并导致未定义的行为(这是最有可能的解释)。

您应该将path中的字符数作为参数len传递,并将path[len] = board[x][y]; path[len + 1] = '\0';手动追加到下一个参数,然后将len + 1传递给递归调用。

  • 当你复制一个在字典中找到的单词时,你忘记了在目标数组中设置空终止符。你应该写:
// verifica se o caminho está presente no conjunto de entrada
    if (Find(path, words) && wordcount < 200) {
        strcpy(answer[wordcount++], path);
    }

相关问题