我有一个文件,其中包含txt文件中的英文单词,每个单词都在一个新行中。
我是C的初学者。我使用load
和unload
函数将所有单词存储到哈希表中(单独链接)并从内存中卸载它们但是遇到了一些问题。
函数(main.c中的代码是正确的):
负载:
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include "dictionary.h"
#define SIZE 26
typedef struct node
{
char word[LENGTH+1];
struct node *next;
}node;
unsigned int hash_num = 0;
node *hashtable[SIZE]; //26 letters in alphabet
node *head = NULL;
// hashfunction
unsigned int hash(char const *key)
{
unsigned int hash= tolower(key[0]) - 'a';
return hash % SIZE;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
unsigned int hash_index=0;
FILE *fp = fopen(dictionary, "r");
if(fp == NULL)
{
fprintf(stderr, "Couldn't open %s",dictionary);
return false;
}
//dictionary
while(!feof(fp))
{
node *temp = malloc(sizeof(node));
if (temp == NULL)
{
unload();
fclose(fp);
return false;
}
if(fscanf(fp , "%s", temp->word) == 1) //storing word of dictionary in my new_node -> word
{
hash_index = hash(temp->word);
head= hashtable[hash_index]; //head always points to first element of linked list (containting word of dictionary)
temp->next = head;
head = temp;
hash_num++;
}
else //if fscanf couldn't store the word (return 0)
{
free(temp); //free last temp
break;
}
}
fclose(fp);
return true;
}
卸载:
bool unload(void)
{
for(int i=0; i<SIZE; i++)
{
if(hashtable[i] != NULL) //if hashtable isn't NULL (has nodes)
{
node *cursor = hashtable[i]; //cursor points at head of individual linked list
while(cursor != NULL) //free them
{
node *temp = cursor;
cursor = cursor->next;
free(temp);
}
}
}
return true;
}
有谁能告诉我逻辑是否正确?每当我运行valgrind时,它告诉我所有节点都已分配,但只有3个空闲&#39; d。
total heap usage: 143,094 allocs, 3 frees, 8,014,288 bytes allocated
LEAK SUMMARY:
==15903== definitely lost: 8,013,040 bytes in 143,090 blocks
==15903== indirectly lost: 0 bytes in 0 blocks
==15903== possibly lost: 0 bytes in 0 blocks
答案 0 :(得分:1)
检查提供的源代码(缺少&#34; dictionary.h&#34;)时,主要问题是位于load()
函数中。
问题1(主要) - 添加新词/节点时hashtable[]
永远不会更新(在计算hash_index = hash(temp->word);
之后)。
要存储更新的链表(管理为反向),它是 必须使用新节点更新
hashtable[hash_index]
指针(已分配的temp
节点)。
temp->next = head;
head = temp;
hashtable[hash_index] = head; // update the hashtable[] pointer
hash_num++;
没有全局变量
head
的替代解决方案。
temp->next = hashtable[hash_index]; //head always points to first element...
hashtable[hash_index] = temp; // update the hashtable[] pointer
hash_num++;
而不是
temp->next = head;
head = temp;
hash_num++;
问题2(小) - hashtable[SIZE]
从未初始化。
在
unload()
函数中,在for循环中,if条件if(hashtable[i] != NULL)
假定数组的每个项目都是 初始化为NULL。
在开头添加load()
函数或在调用它之前,使用for循环初始化每个指针。
for(int i=0; i<SIZE; i++)
{
hashtable[i] = NULL;
}
问题3(潜在错误来源) - 正如评论者所建议的,使用head
,声明为全局变量node *head = NULL;
可能是错误的潜在来源。
在
load()
函数中,变量head
用作临时变量 存储但可以在软件运行期间存储价值。如果是读操作 结果是在没有熟知的写操作之前执行的 即使编译没有检测到,也可能是意外错误 错误或警告。最好的方法是减少全局变量的数量 可能的。
增强功能(反向链接列表) - 因为托管链接列表正在前面添加新项目,所以这是最终添加新项目的解决方案。
node *first = hashtable[hash_index];
if (first == NULL) {
hashtable[hash_index] = temp;
}
else {
temp->next = NULL; // ending the list
while (first->next!=NULL) {
first = first->next; // loop until last node
}
first->next = temp; // linking to the last node
}
hash_num++;
而不是
head= hashtable[hash_index]; //head always points to first element ...
temp->next = head;
head = temp;
hash_num++;