C语言中的拼写检查
我一直在尝试使用一个大字典来实现一个拼写检查器,它针对一些包含大约2000个单词的文本文件。但是,我的拼写检查器返回所有拼写错误的单词。我真的不知道为什么-有人能帮我吗C语言中的拼写检查,c,arrays,pointers,cs50,C,Arrays,Pointers,Cs50,我一直在尝试使用一个大字典来实现一个拼写检查器,它针对一些包含大约2000个单词的文本文件。但是,我的拼写检查器返回所有拼写错误的单词。我真的不知道为什么-有人能帮我吗 #include <stdbool.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include "dictionary.h" #define le
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "dictionary.h"
#define lenght 45
#define hashtable_size 65536
char word[lenght+1];
int count = 0;
/*
*
* Hash function. Thanks to Brenda from cs50 reddit.
*/
int hash_it(const char* needs_hashing)
{
unsigned int hash = 0;
for (int i=0, n=strlen(needs_hashing); i<n; i++)
hash = (hash << 2) ^ needs_hashing[i];
return hash % hashtable_size;
}
typedef struct node
{
char* word;
struct node* next;
}node;
node* previous;
node* hashtable[hashtable_size];
/*
*
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
char word[lenght+1];
FILE* dict = fopen(dictionary,"r");
for(int i = 0; i < 26;i++)
{
hashtable[i] = NULL;
for(int a = fgetc(dict); a != EOF; a = fgetc(dict))
{
count++;
int hashvalue = hash_it(word);
node* new = malloc(sizeof(node));
if(hashtable[hashvalue] == NULL)
{
hashtable[hashvalue] = new;
new -> next = NULL;
}
else
{
new -> next = hashtable[hashvalue];
hashtable[hashvalue] = new;
}
}
}
fclose(dict);
return true;
}
/*
*
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
char tmp[lenght + 1];
int lenghtw = strlen(word);
for (int i = 0; i < lenghtw; i++)
{
tmp[i] = tolower(word[i]);
}
int index = hash_it(tmp);
if (hashtable[index] == NULL)
{
return false;
}
node* cursor = hashtable[index];
while(cursor != NULL)
{
if(strcmp(tmp, cursor -> word) == 0)
{
return true;
}
cursor = cursor -> next;
}
return false;
}
/*
*
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
return count;
}
/*
*
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
int index = 0;
while(index < hashtable_size)
{
if(hashtable[index] == NULL)
{
index++;
}
else
{
while(hashtable[index] != NULL)
{
node* cursor = hashtable[index];
hashtable[index] = cursor -> next;
free(cursor);
}
index++;
}
}
return true;
}
int main(int argc, char **argv)
{
if (argc != 2)
return 3;
if (!load("dictionary"))
return 1;
printf("loaded %d words\n", size());
printf("word '%s'%s found\n", argv[1], check(argv[1]) ? "" : " not");
unload();
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括“dictionary.h”
#定义长度45
#定义哈希表大小65536
字符字[长度+1];
整数计数=0;
/*
*
*散列函数。感谢cs50 reddit的Brenda。
*/
int散列(const char*需要散列)
{
无符号整数散列=0;
for(int i=0,n=strlen(需要散列);i next=hashtable[hashvalue];
hashtable[hashvalue]=新的;
}
}
}
fclose(dict);
返回true;
}
/*
*
*如果单词在字典中,则返回true,否则返回false。
*/
布尔检查(常量字符*单词)
{
字符tmp[长度+1];
int lenghtw=strlen(字);
对于(int i=0;i单词)==0)
{
返回true;
}
光标=光标->下一步;
}
返回false;
}
/*
*
*如果已加载,则返回字典中的字数;如果尚未加载,则返回0。
*/
无符号整数大小(void)
{
返回计数;
}
/*
*
*从内存中卸载字典。如果成功,则返回true;否则返回false。
*/
bool卸载(无效)
{
int指数=0;
while(索引<哈希表大小)
{
if(哈希表[索引]==NULL)
{
索引++;
}
其他的
{
while(哈希表[索引]!=NULL)
{
节点*游标=哈希表[索引];
哈希表[索引]=光标->下一步;
自由(光标);
}
索引++;
}
}
返回true;
}
int main(int argc,字符**argv)
{
如果(argc!=2)
返回3;
如果(!加载(“字典”))
返回1;
printf(“加载了%d个字,\n”,size());
printf(“找到单词'%s'%s\n',argv[1],检查(argv[1])?”“:“未”);
卸载();
返回0;
}
您的代码中有许多问题:
- 在
函数中,您不会将字典中的单词加载到哈希表中。您可以使用load
一次读取一个字符,并从未初始化的本地缓冲区fgetc()
创建一个节点word
函数只对单词的最后16个字符进行哈希运算。此外,hashtable\u-it
是2的幂,这是一个坏主意。实际上,只有最后8个字符参与哈希值。这不是一个错误,只是一种低效的哈希方法hashtable\u-size
- 在
函数中,复制单词并将其转换为小写,但忘记将check
数组的最后一个字节设置为tmp
'\0'
load
,它在每行字典中读取一个单词:
bool load(const char *dictionary) {
char line[256];
FILE *dict = fopen(dictionary, "r");
if (!dict)
return false;
while (fgets(line, sizeof line, dict) != NULL) {
char *p = line + strspn(line, " \t"); // skip blanks
p[strcspn(p, " \t\r\n")] = '\0'; // strip trailing blanks
if (*p == '\0' || *p == '#' || *p == ';')
continue; // ignore blank lines and comments
count++;
int hashvalue = hash_it(p);
node *np = malloc(sizeof(node));
np->word = strdup(p);
np->next = hashtable[hashvalue];
hashtable[hashvalue] = np;
}
fclose(dict);
return true;
}
请提供一个。特别是一个
main
函数,该函数显示如何设置字典、如何调用check
以及输入文件包含的内容。我格式化了代码,注意到没有main()
function。鉴于目前为止的答案,很明显,您最好在调试器中单步执行此代码并观察变量状态和代码流,而不是要求调试器为您调试它。使用调试器总是比发布代码和问题更有效的调试方法。如果您从未使用过调试器,则您需要花费的时间基本功能(如果您不只是使用GDB命令行调试器,可能会少一些,如果您使用Visual Studio,可能会少一些)将为您节省许多小时的开发时间。IMHO,您可以删除不使用的行声明,并且可能会强调由strdup()分配的缓冲区
需要释放。检查一下哈希表[hashvalue]
在将节点放入内部之前为NULL可能会防止出现异常行为collision@OznOg:感谢您指出不一致之处。实际上没有使用全局数组word
。启动时,全局数组哈希表[]中的所有条目
初始化为NULL
,因此不需要额外的检查。如果插槽为空,np->next
接收NULL
,否则np
在列表前面。检查是关于哈希中的冲突,如果我理解,它将自动失败correctly@OznOg:一点也不,支票是多余的hashtable是一个插槽数组,每个插槽都有一个具有相同hashvalue的节点列表。上面的代码将节点插入列表开头的适当插槽中。谢谢!您帮了我很多忙。在实现代码之前,我将花时间回顾和理解代码。