此函数应该将字典加载到 trie 中。我想知道字典文件有多大,这样我就可以一次调用
所有内存。这样做的原因是所有内存都靠近在一起,因此可以利用有助于加快搜索速度的硬件。我也找到了 2 种方法的建议。其中之一是您将在我的代码中看到的 sys/stat.h
的使用。
当我运行这段代码时,我收到一个“段错误”,我知道这意味着我正在尝试访问我没有权限的内存。通过使用 GDB 我发现段错误发生在第 116 行(又名:读取“else if (cur->children[key] == NULL)”的行)我发现 key 中的值在那时间是 12。起初我认为问题出在我对 calloc
或 sys/stat.h
的使用上,因为这是我对它们了解最少的两件事利用。然而,我对它们的研究越多,这种可能性就越小。如果不是其中之一,那么我什至不知道该去哪里找。
下面只是我认为相关的代码:
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/stat.h>
#include "dictionary.h"
typedef struct node
{
bool end[26];
struct node* children[26];
} node;
node* start;
int key;
int last;
int dic_count;
bool load(const char* dictionary)
{
struct stat s;
stat(dictionary, &s);
int size = s.st_size;
dic_count = 0;
int z = 1;
FILE* dic = fopen(dictionary, "r");
if (dic == NULL)
{
return false;
}
start = calloc(size, sizeof(node));
if (start == NULL)
{
return false;
}
int l = 0;
int d;
node* cur = &start[0];
while (0 != (d = fgetc(dic)))
{
int d = fgetc(dic);
if (l > 0)
{
last = key;
}
l = 1;
key = d - 'a';
if (d == '\n')
{
cur->end[last] = true;
cur = &start[0];
dic_count++;
}
else if (cur->children[key] == NULL)
{
node* new = &start[z];
cur->children[key] = new;
z++;
if (cur->children[key] == NULL)
{
return false;
}
cur = cur->children[key];
}
else
{
cur = cur->children[key];
}
}
return true;
}
非常感谢任何帮助。
最佳答案
您确定您的文件包含二进制 0 吗?如果您尝试读取文件末尾,请针对 EOF 测试 fgetc
结果,而不是 0。否则您的循环永远不会终止。
除此之外,您只处理每个第二个字符。
按要求扩展:
来自 man fgetc
:
fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error
您可能将它与 fgets
返回值混淆了。
while ((ch = fgetc(fp)) != EOF)
安然无恙。同样,可能造成混淆的原因是
while (!feof(fp))
现在,关于未处理的字符:你写了
while (0 != (d = fgetc(dic)))
{
int d = fgetc(dic);
代码读取 while
表达式中的一个字符,将其与 0 进行比较,然后读取(下一个)字符。第一个字符丢失。
关于c - 段错误加载字典。它是由 calloc、sys/stat.h 还是其他原因引起的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26264055/