私は、テキストファイルをスペルチェックするためのトライデータ構造を実装しようとしています。現在、ファイル内のカップルワードで動作するように見えますが、segフォルトになります。私は犯人を見つけるためにデバッグを試みましたが、私が見つけたのは、 "文字"の値が一見ランダムな負の値を保持しているということでした(それは1と27の間でなければなりません)。通常、segフォルトの問題はプログラムを開始した直後に表示されるので、なぜプログラムの途中で問題が発生しているのかわかりません。CのTrie実装でのセグメンテーションフォルト
/**
* Implements a dictionary's functionality.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "dictionary.h"
//create global root node
Trienode *root;
//create word counter for size() function
unsigned int wordcount = 0;
//creates an empty node
Trienode * newnode()
{
Trienode *nnode = NULL;
nnode = (Trienode *)malloc(sizeof(Trienode));
//initialize new node with null pointers and values
nnode -> parent = NULL;
for(int i = 0; i < 27; i++)
{
nnode -> children[i] = NULL;
}
return nnode;
}
void cleartrie(Trienode *head)
{
//if child node exists, free it, else continue with next iteration in for loop
if(head)
{
for(int i = 0; i < 27; i++)
{
cleartrie(head -> children[i]);
}
free(head);
head = NULL;
}
}
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char *word)
{
int i = 0;
int letter;
Trienode *head = root;
while(word[i] != '\0')
{
if(isalpha(word[i]))
{
letter = word[i] - 'a';
}
else //it must be an apostrophe
{
letter = word[i] - 13;
}
if(!(head -> children[letter]))
{
return false;
}
else //a pointer must exist
{
head = head -> children[letter];
}
i++;
}
return true;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char *dictionary)
{
//open file
FILE *infile = fopen(dictionary, "r");
Trienode *parnode; //parent node
root = newnode();
Trienode *curnode = root; //current node
int letter = 0;
//while not end of file, read words
while(fgetc(infile) != EOF)
{
//while not end of word, read letters
for(;;)
{
int c;
//read current letter in file
c = fgetc(infile);
//convert input char to corresponding array location (a - z = 0-25, apostrophe = 26)
if(isalpha(c))
{
letter = c - 'a';
}
else if (c == '\'')
{
letter = c - 13;
}
//if end of string, exit loop
else if (c == '\0')
{
//end of word, so endofstring = true
wordcount++;
break;
}
//move to next letter if not either apostrophe or alphabetical
else
{
break;
}
//if pointer to letter of word doesn't exist, create new node
if(curnode -> children[letter] == NULL)
{
curnode -> children[letter] = newnode();
}
//child node is the new current node
parnode = curnode;
curnode = curnode -> children[letter];
curnode -> parent = parnode;
}
//return to root node
curnode = root;
}
fclose(infile);
return true;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
return wordcount;
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
cleartrie(root);
if (root == NULL)
{
return true;
}
return false;
}
テキストの壁には申し訳ありませんが、大部分は文脈のためだけです(私は願っています)。 segフォールトエラーは、チェックヘルパー関数のif(!(head - > children [letter]))行で発生しています。
ありがとうございます!
あなたのコードにTrienodeが何であるかわかりません。それは構造体ですか? – Jerinaw
デバッガを使用しましたか?あなたのコードのどの部分にセット・フォルトが正確に発生しますか(デバッガはあなたに指示する必要があります)? 'letter 'の価値がどこまで狂っているのが分かりますか?これは部分的なコードリストなので(問題を絞り込むことなくすべてのコードを記述することはお勧めしません)、問題がどこを見ているのかを言うのは難しいです。より多くのデバッグを行い、それを絞り込んでください。 – lurker
valgrindを使用します。あなたの問題がどこにあるか教えてくれます。 –