抱歉打扰,但我不明白为什么代码不起作用。如果我使用全局指针调用函数,它会传递地址,但当我尝试转到下一个节点时,它只会返回 (nil)。此外,如果我在生成函数中打印下一个节点的指针,它也可以正常工作。那么发生了什么?
Info: length = 1, tmp_word = a, line 214 or ctrl + f nil.
// Implements a dictionary's functionality
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include "dictionary.h"
// Load variables:
char *dict_word;
FILE *dict;
// Size variables:
unsigned int count_words = 0;
// Structure
const int nodes = 27; // 26 letters + '.
int heigth = 3;
typedef struct hash_table
{
char word[46]; // 45 letters + NULL.
struct hash_table *next;
}
hash_table;
typedef struct trie
{
bool is_word;
struct trie *character[nodes];
hash_table *next;
}
trie;
trie *root;
// Generate structure.
trie *generate(int times);
// Assign to the structure created.
void hash_(trie *any);
void assign(trie *any, int length, int index, char *tmp_word);
void assign_v2(trie *any, int heigth_b, int index, char *tmp_word);
void assign_v2b(hash_table *any, char *tmp_word);
// Free.
void free_hashtable(trie *any, int times);
void free_hashtable2(hash_table *any);
void free_trie(trie *any);
// Check.
bool check_trie(const char *word, int length, trie *any, int index);
bool check_trie_v2(const char *word, int length, trie *any, int index);
bool check_hash(const char *word, hash_table *any);
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
int length = strlen(word);
if (length <= 3)
{
return check_trie(word, length, root, 0);
}
else if (length > 3)
{
return check_trie_v2(word, heigth, root, 0);
}
return false;
}
// DONE
bool load(const char *dictionary)
{
dict = fopen(dictionary, "r");
if (dict == NULL)
{
printf("Could not load the file\n");
return false;
}
if (fseek(dict, 0, SEEK_END) == -1)
{
return false;
}
long x;
if ((x = ftell(dict)) == - 1)
{
return false;
}
rewind(dict);
dict_word = malloc(x);
if (dict_word == NULL)
{
return false;
}
fread(dict_word, 1, x, dict);
root = generate(3);
hash_(root);
return true;
}
// DONE
unsigned int size(void)
{
if (count_words != 0)
{
return count_words;
}
else
{
return 0;
}
}
bool unload(void)
{
free(dict_word);
free_hashtable(root, heigth);
free_trie(root);
free(root);
if (fclose(dict)!= 0)
{
return false;
}
else
{
return true;
}
}
trie *generate(int times)
{
// Allocate memory to root, to character[i]
// and also change the access of character[i] to root.
// So in the second run, root would be equivalent to
// root->character[i].
root = malloc(sizeof(trie));
root->next = NULL;
if (times > 0)
{
for (int i = 0; i < nodes; i++)
{
// For every single pointer generates more nodes pointers.
root->character[i] = generate(times - 1);
}
}
else
{
for (int i = 0; i < nodes; i++)
{
// Set all remaining pointers to null
// as there aren't more arrays.
root->character[i] = NULL;
}
// Malloc for new structure.
root->next = malloc(sizeof(hash_table));
root->next->next = NULL;
}
// Return the address of root,
// so the root in the main function can point
// to the trie created.
return root;
}
void hash_(trie *any)
{
char *tmp_word = calloc(1, 46);
char c;
int length = 0;
for (int i = 0; dict_word[i] != '\0'; i++)
{
c = dict_word[i];
strncat(tmp_word, &c, 1);
if (dict_word[i + 1] == '\n')
{
length = strlen(tmp_word);
if (length <= heigth)
{
assign(root, length, 0, tmp_word);
free(tmp_word);
i++;
}
else
{
assign_v2(root, heigth, 0, tmp_word);
free(tmp_word);
i++;
}
}
}
}
void assign(trie *any, int length, int index, char *tmp_word)
{
printf("%p\n", any); // root
printf("%p\n", any->character[0]); // nil
if (length != 0)
{
if (tmp_word[index] != '\'')
{
assign(any->character[1], length - 1, index + 1, tmp_word);
}
else
{
assign(any->character[26], length - 1, index + 1, tmp_word);
}
}
any->is_word = 1 // nil, core dump
return;
}
void assign_v2(trie *any, int heigth_b, int index, char *tmp_word)
{
if (heigth_b != 0)
{
if (tmp_word[index] != '\'')
{
assign_v2(any->character[tmp_word[index] - 97], heigth_b - 1, index + 1, tmp_word);
}
else
{
assign_v2(any->character[26], heigth_b - 1, index + 1, tmp_word);
}
}
else
{
assign_v2b(any->next, tmp_word);
return;
}
}
void assign_v2b(hash_table *any, char *tmp_word)
{
// Create a tmp pointer to last word.
hash_table *tmp = any;
// Malloc and assign new word.
hash_table *new = malloc(sizeof(hash_table));
strcpy(new->word, tmp_word);
// Make root point to the same location as new_word.
any = new;
// Move first word to the right.
any->next = tmp;
return;
}
void free_hashtable(trie *any, int times)
{
for (int i = 0; i < nodes; i++)
{
if (times > 1)
{
free_hashtable(any->character[i], times - 1);
}
}
if (times == 1)
{
for (int i = 0; i < nodes; i++)
{
//Where root is root->character[i]->character[i]
if (any->character[i]->next->next != NULL)
{
free_hashtable2(any->character[i]->next);
}
free(any->character[i]->next);
}
}
return;
}
void free_hashtable2(hash_table *any)
{
if (any->next != NULL)
{
free_hashtable2(any->next);
free(any->next);
}
return;
}
void free_trie(trie *any)
{
for (int i = 0; i < nodes; i++)
{
if (any->character[i] != NULL)
{
// Calls function first so it can works backwards.
free_trie(any->character[i]);
free(any->character[i]);
}
}
return;
}
bool check_trie(const char *word, int length, trie *any, int index)
{
if (length != 0)
{
if (word[index] == '\'')
{
check_trie(word, length - 1, any->character[26], index + 1);
}
else if (isupper(word[index]) != 0)
{
check_trie(word, length - 1, any->character[word[index] - 65], index + 1);
}
else if (islower(word[index]) != 0)
{
check_trie(word, length - 1, any->character[word[index] - 97], index + 1);
}
}
if (any->is_word == 1)
{
return true;
}
else
{
return false;
}
}
bool check_trie_v2(const char *word, int length, trie *any, int index)
{
if (length != 0)
{
if (word[index] == '\'')
{
check_trie_v2(word, length - 1, any->character[26], index + 1);
}
else if (isupper(word[index]) != 0)
{
check_trie_v2(word, length - 1, any->character[word[index] - 65], index + 1);
}
else if (islower(word[index]) != 0)
{
check_trie_v2(word, length - 1, any->character[word[index] - 97], index + 1);
}
}
return check_hash(word, any->next);
}
bool check_hash(const char *word, hash_table *any)
{
if (any != NULL)
{
if (strcmp(word, any->word) == 0)
{
return true;
}
else
{
check_hash(word, any->next);
}
}
if (any == NULL)
{
return false;
}
return false;
}
程序在第 231 行得到一个核心转储
对不起,有点乱。谢谢!
我试着用关/开做一个迷你功能。该函数接受一个新的 int 值 1。然后我做了 any = root 和 on = 0。因为我确实认为这个问题在某种程度上与函数参数的全局变化有关,但它没有用。