【发布时间】:2020-08-18 22:37:05
【问题描述】:
我是 CS 新手,真的可以在拼写器 pset 上使用一些帮助。我有一个基本的大纲,似乎没有段错误,但我仍然有问题。它未能通过 check50:
- 它不能正确处理大多数基本单词
- 拼写检查不区分大小写
- 它不能正确处理子字符串
- 并且有内存错误
如果我通过它运行一个测试文件,计数器只显示字典中有 2 个单词,因此它几乎将文档中的每个单词都吐出为拼写错误(导致我认为加载有错误,但我不知道在哪里)。
还有一个 valgrind 错误。它显示以下内容:
堆摘要:在退出时使用:14 个块中的 1,300 个字节。 总堆使用量:15 次分配,1 次释放,分配了 5406 字节。
任何帮助将不胜感激;我已经坚持了 3 天!
#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <stdlib.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 26;
// Hash table
node *table[N];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
int numloc = hash(word);
node *cursor = table[numloc];
while (cursor != NULL)
{
if (strcasecmp(cursor->word, word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
unsigned long hash = 5381;
int c;
while ((c = *word++))
{
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
}
return hash % N;
}
// Loads dictionary into memory, returning true if successful else false
int counter = 0;
bool load(const char *dictionary)
{
FILE *dictionary = fopen(dictionary, "r");
if (dictionary == NULL)
{
return false;
}
char tempword[LENGTH + 1];
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
while (fscanf(dict, "%s", tempword) != EOF)
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
strcpy(n->word, tempword);
int A = hash(tempword);
if (table[A] == NULL)
{
table[A] = n;
n->next = NULL;
}
else
{
n->next = table[A];
table[A] = n;
}
counter++;
}
fclose(dictionary);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
if (counter == 0)
{
unload();
return 1;
}
else
{
return counter;
}
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
for (int i = 0; i < N; i++)
{
node *cursor = table[i];
node *tmp = table[i];
while (cursor != NULL)
{
cursor = cursor->next;
free(tmp);
tmp = cursor;
}
return true;
}
return false;
}
【问题讨论】:
-
为了不区分大小写,您应该只使用大写或小写字母进行散列(您选择哪个)。
tolower()或toupper()会有所帮助。 -
另外,使用原始评论
hash * 33而不是移位/添加。如果效率更高,编译器可以非常聪明地使用移位/加法。 -
BTW 的主要代码和其余代码在哪里?
-
对于堆分配函数的每次调用:
calloc()malloc()realloc()必须在程序退出之前调用free(),使用与堆返回的指针值相同的指针值分配函数。 -
编译时,始终启用警告。然后修复这些警告。 (对于
gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu11)注意:其他编译器使用不同的选项来产生相同的结果。