我正在运行一个程序,该程序通过读取'words.txt'中的单词来创建字典树,然后可以搜索以查看某些单词是否在树中。在https://www.onlinegdb.com/online_c_compiler上运行该程序可以很好地工作,但是当我尝试在自己的Linux系统上运行该程序时,出现了段错误。有什么想法吗?这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Node structure of trie */
struct node
{
struct node *next[27]; // 26 for a-z and last one(26th index) is for apostrophe
int end; // value as 1 denotes the end of the word.
};
/* This method is for creating a new node */
struct node *createNode()
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->end = 0; // set end as false i.e. 0
for (int i = 0; i < 27; i++) // set all children as NULL
newNode->next[i] = NULL;
return newNode;
}
/* This method is for inserting a word in the trie */
void insert(struct node *root, char *word)
{
struct node *curr = root;
for (int i = 0; i < strlen(word); i++) // iterating character by character
{
int index;
if (word[i] == '\'') // if character is apostrophe index is 26
index = 26;
else
index = tolower(word[i]) - 'a'; // else the index as the alphabet sequence number starting from 0.
// for a - 0, b - 1, ..... z - 25
if (!curr->next[index])
curr->next[index] = createNode(); // create node of that character if not created yet
curr = curr->next[index]; // then go for next character
}
curr->end = 1; // mark end as 1 to denote the ending of the word
}
/* This method is for searching a word in the trie */
int search(struct node *root, char *word)
{
struct node *curr = root;
for (int i = 0; i < strlen(word); i++) // iterating character by character
{
/* Getting index same as insert function */
int index;
if (word[i] == '\'')
index = 26;
else
index = tolower(word[i]) - 'a';
if (!curr->next[index]) // if node of current character not found means the word doesn't exist in trie.
return 0;
curr = curr->next[index];
}
if (curr != NULL && curr->end) // if iterated all the characters and end is 1 then the word exists.
return 1;
else
return 0; // otherwise doesn't exist.
}
int main()
{
/* Reading the file line by line */
FILE *file;
size_t len = 1000;
char *word = (char *)malloc(len);
file = fopen("word.txt", "r");
struct node *root = createNode();
while (fgets(word, len, file) != NULL) // iterating line by line
{
int len = strlen(word);
if (word[len - 1] == '\n') // removing the newline which is at the end of the every line
word[len - 1] = '\0';
insert(root, word); // inserting every word
}
int ans;
word = (char *)("error's"); // checking the existence of the word "error's"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
word = (char *)("hilli");// checking the existence of the word "hilli"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
return 0;
}
这里的代码应该有效。它确实可以在使用GCC 9.2.0和XCode 11.3.1的macOS 10.15.2 Catalina上工作,并且编译器设置为fussy并启用了许多内存调试选项。它不会尝试释放它所建立的特里;它应该(能够释放您构建的结构是一个很好的练习)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Node structure of trie */
struct node
{
struct node *next[27]; // 26 for a-z and last one(26th index) is for apostrophe
int end; // value as 1 denotes the end of the word.
};
/* This method is for creating a new node */
static struct node *createNode(void)
{
struct node *newNode = (struct node *)malloc(sizeof(struct node));
newNode->end = 0; // set end as false i.e. 0
for (int i = 0; i < 27; i++) // set all children as NULL
newNode->next[i] = NULL;
return newNode;
}
/* This method is for inserting a word in the trie */
static void insert(struct node *root, char *word)
{
struct node *curr = root;
int length = strlen(word);
for (int i = 0; i < length; i++) // iterating character by character
{
int index;
if (word[i] == '\'') // if character is apostrophe index is 26
index = 26;
else
index = tolower(word[i]) - 'a'; // else the index as the alphabet sequence number starting from 0.
// for a - 0, b - 1, ..... z - 25
if (!curr->next[index])
curr->next[index] = createNode(); // create node of that character if not created yet
curr = curr->next[index]; // then go for next character
}
curr->end = 1; // mark end as 1 to denote the ending of the word
}
/* This method is for searching a word in the trie */
static int search(struct node *root, char *word)
{
struct node *curr = root;
int length = strlen(word);
for (int i = 0; i < length; i++) // iterating character by character
{
/* Getting index same as insert function */
int index;
if (word[i] == '\'')
index = 26;
else
index = tolower(word[i]) - 'a';
if (!curr->next[index]) // if node of current character not found means the word doesn't exist in trie.
return 0;
curr = curr->next[index];
}
if (curr != NULL && curr->end) // if iterated all the characters and end is 1 then the word exists.
return 1;
else
return 0; // otherwise doesn't exist.
}
int main(void)
{
/* Reading the file line by line */
FILE *file;
size_t len = 1000;
char *word = (char *)malloc(len);
const char filename[] = "word.txt";
file = fopen(filename, "r");
if (file == 0)
{
fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
exit(EXIT_FAILURE);
}
struct node *root = createNode();
while (fgets(word, len, file) != NULL) // iterating line by line
{
//int len = strlen(word);
//if (word[len - 1] == '\n') // removing the newline which is at the end of the every line
// word[len - 1] = '\0';
word[strcspn(word, "\r\n")] = '\0';
printf("Word: [%s]\n", word);
insert(root, word); // inserting every word
}
int ans;
word = (char *)("error's"); // checking the existence of the word "error's"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
word = (char *)("hilli");// checking the existence of the word "hilli"
ans = search(root, word);
if (ans == 1)
printf("\"%s\" found!\n", word);
else
printf("\"%s\" not found!\n", word);
return 0;
}
给定包含这些行的适当子集的数据文件,代码可以正确运行:
enough
abracadabra
acid
test
hilli
error's
tests
testing
tested
tester
testosterone
acidly
acidic
[它已经在DOS(CRLF)和Unix(NL或LF)的行尾进行了测试,并且两者都比较安全,因为它使用strcspn()
来换行任何一种行尾:
word[strcspn(word, "\r\n")] = '\0';
[如果您有旧的Mac风格的行尾(仅CR),那么您会遇到fgets()
无法识别行尾的问题-但如果您将其固定(例如使用POSIX getdelim()
),则会出现问题这样的线也可以正常工作。
对您的代码所做的更改基本上是表面上的修饰,但是允许使用相当严格的选项将代码进行干净地编译(源getdelim()
;程序trie79.c
:]]
trie79