我正在使用3个文件制作trie:speller.c是主文件,dictionary.c包含函数& global root trie pointer,dictionary.h声明了一个字典的函数。 在dictionary.c中完成函数加载后,全局根指针值出现问题。
speller.c
int main(int argc, char* argv[])
{
// load dictionary
char* dictionary = TMPDICT;
bool loaded = load(dictionary);
// abort if dictionary not loaded
if (!loaded)
{
printf("Could not load %s.\n", dictionary);
return 1;
}
//next I need to call check function, but root value is missing here
}
dictionary.c
typedef struct TrieNode
{
struct TrieNode **children;
bool is_word;
} TrieNode;
struct TrieNode * root;
struct TrieNode *create_trienode(char c, struct TrieNode *parent);
bool load(const char* dictionary)
{
FILE * file = fopen(dictionary, "r");
if (file == NULL)
{
printf("trie: No such file(dictionary)\n");
return 1;
}
struct TrieNode *root = create_trienode(' ', NULL);
struct TrieNode *ptr = root;
int character;
int converted;
int buffer;
//This handles if file does not end with a newline
character = fgetc(file);
buffer = fgetc(file);
while(character != EOF)
{
character = tolower(character);
if (character == 10) // if newline, start new word read
{
}
else
if(isalpha(character))
{
converted = character - 'a';
if(ptr->children[converted] == NULL)
{
ptr->children[converted] = create_trienode(character, ptr);
}
ptr = ptr->children[converted];
}
if (character == SLASHNUM) //if backslash
{
if(ptr->children[SLASH_TMP] == NULL)
{
ptr->children[SLASH_TMP] = create_trienode(character, ptr);
}
ptr = ptr->children[SLASH_TMP];
}
if(ptr != root && (!(character == SLASHNUM || isalpha(character)) || buffer == EOF))
{
ptr->is_word = true;
ptr = root;
word_count++;
}
character = buffer;
buffer = fgetc(file);
}
return true;
}
struct TrieNode *create_trienode(char c, struct TrieNode *parent)
{
struct TrieNode *node = malloc(sizeof(struct TrieNode));
node->children = malloc(ALPHABET_SIZE * sizeof(struct TrieNode*));
node->is_word=false;
for (int i = 0; i < ALPHABET_SIZE; i++)
{
node->children[i] = NULL;
}
return node;
}
GDB
Breakpoint 1, load (dictionary=0x80489c4 "tmpDict") at dictionary.c:100
100 character = fgetc(file);
(gdb) info locals
file = 0x804b008
root = 0x804b170
ptr = 0x804b170
character = 1267019363
converted = 262929407
buffer = 1266804984
(gdb) c
Continuing.
Breakpoint 2, main (argc=1, argv=0xbffff0d4) at speller.c:40
$1 = (struct TrieNode *) 0x0
(gdb)
如何在speller.c中显示root?另外在任务中说我不能改变speller.c
答案 0 :(得分:5)
通常,您需要在 dictionary.h 文件中将root
声明为extern
,并将该头文件包含在 speller.c
这样,root
将可用于翻译单元 spleller.c 。接下来,您可以在 speller.c 中使用root
,就像任何其他本地变量(在该文件本身中已定义)一样。
[正如Mr. alk在以下评论中正确指出的那样]
问题此处是本地 root
变量的定义
struct TrieNode *root = create_trienode(' ', NULL);
在load()
函数内实际阴影全局root
struct TrieNode * root;`
因此,全局root
永远不会更新。
相关,来自C11
标准,章节§6.2.1(强调我的)
[...]如果标识符指定同名的两个不同实体 空间,范围可能重叠。如果是这样,一个实体的范围(内部范围)将结束 严格地在另一个实体的范围之前(外部范围)。 在内部范围内, identifier指定在内部作用域中声明的实体;在外部宣布的实体 范围在内部范围内隐藏(并且不可见)。
答案 1 :(得分:1)
您的代码定义root
两次,其中load()
的本地定义会影响全局定义。
这一行
struct TrieNode *root = create_trienode(' ', NULL);
在本地定义root
,并将create_trienode()
的结果分配给root
的本地定义。
根据root
on的本地定义,全局定义的root
会被本地定义,并且无法再访问。
要解决此更改:
struct TrieNode *root = create_trienode(' ', NULL);
struct TrieNode *ptr = root;
到
struct TrieNode *ptr= create_trienode(' ', NULL);
root = ptr;