我目前正在为 CS50 开发 PSET5 拼写器。我正在尝试实现哈希表并尝试一起加载字典。问题是它一直显示分段错误,我似乎找不到问题所在。我的代码有错误还是无法正常工作?
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
bool is_word;
struct node *children[26];
}
node;
// TODO: Choose number of buckets in hash table
const unsigned int N = 71;
// Hash table
node *table[N];
//Counts words
int word_count = 0;
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO: Improve this hash function
return tolower(word[0]) - 'a';
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
for (int z = 0; z<71; z++) {
table[z] = malloc(sizeof(node));
for (int i = 0; i<26; i++) {
table[z]->children[i] = NULL;
}
}
FILE *file = fopen(dictionary, "r");
if (file == NULL)
{
printf("Could not open %s.\n", dictionary);
unload();
return 1;
}
int index = 0;
char word[LENGTH + 1];
char c;
while (fread(&c, sizeof(char), 1, file)) {
if (isalpha(c) || (c == '\'' && index > 0)) {
word[index] = c;
index++;
}
else if (index>0) {
word[index] = '\0';
word_count +=1;
int hashword = hash(word);
node *cursor = table[hashword];
for (int j = 0; j<index; j++) {
int letterindex = tolower(word[j]) - 'a';
if (cursor->children[letterindex] == NULL) {
node *new = malloc(sizeof(node));
if (new == NULL) {
printf("ERROR NULL!");
return 0;
}
new->is_word = false;
for (int k = 0; k<26; k++) {
new->children[k] = NULL;
}
cursor->children[letterindex] = new;
}
cursor = cursor->children[letterindex];
}
cursor->is_word = true;
index = 0;
}
}
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
return word_count;
}
void unloader(node* current)
{
for (int i = 0; i < 26; i++)
{
if (current->children[i] != NULL)
{
unloader(current->children[i]);
}
}
free(current);
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
for (int i = 0; i<N; i++) {
if (table[i] != NULL) {
unloader(table[i]);
}
}
return true;
}
考虑:
if (isalpha(c) || (c == '\'' && index > 0)) {
word[index] = c;
index++;
}
代码将“字母状态”授予单个撇号(0x27)(例如:“
don't
”)
children
的数量。
后来:
int letterindex = tolower(word[j]) - 'a';
0x27 (
'\''
) - 0x61 ('a'
) ==>(负索引)
因此任何使用
cursor->children[letterindex]
都会调用 UB...
可能还有更多,但这可能是一个主要错误。