为 hashmap 创建可变数量的链表
Creating a variable amount of linked lists for hashmap
以下是我的代码的重要部分,无用部分已被注释掉:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "hmap.h"
struct val_word{
char *final_word;
struct val_word* next;
};
int main (int argc, char **argv){
//Check if dictionary file is given
FILE *fp1;
char key [125];
char val [125];
char temp;
struct val_word *storage;
char c;
int i;
int j;
int l;
HMAP_PTR dictionary = hmap_create(0, 0.75);
fp1 = fopen(argv[1], "r");
do{
c = fscanf(fp1, "%s", key);
// Convert string to lowercase
strcpy(val, key);
//Alphabetically sort string
struct val_word* word_node = malloc(sizeof(struct val_word));
word_node->final_word = val;
word_node->next = NULL;
storage = hmap_get(dictionary, key);
if(storage == NULL){
hmap_set(dictionary, key, word_node);
}
else{
struct val_word *temp2 = storage;
while(temp2->next != NULL){
temp2 = temp2->next;
}
word_node->final_word = val;
word_node->next = NULL;
temp2->next = word_node;
hmap_set(dictionary, key, storage);
}
} while (c != EOF);
fclose(fp1);
while(storage->next != NULL){
printf("The list is %s\n", storage->final_word);
storage = storage->next;
}
return 0;
}
我得到了一个未知长度的字典文件,以及一个我无法触摸的散列 table 实现文件。散列 table 存储单词的混乱版本,键是单词按字母顺序排序的版本。例如:
部分词典包含:leloh, hello, elloh, holel
key 将是:ehllo
val就是一个链表,存储了上述4个词。
hmap_get 获取给定键的值,hmap_set 设置给定键的值。
我的代码处理一切正常,直到我尝试打印位于某个键的列表。
该列表将具有正确的大小,但仅存储作为输入的 LAST 值。因此,添加到上面的示例中,我的列表将是(按时间顺序):
- 乐乐
- 你好 -> 你好
- 洞 -> 洞 -> 洞
- ehllo -> ehllo -> ehllo -> ehllo
出于某种原因,它还将正确按字母顺序排列的字符串存储为最后一个字符串,我没有提供 hmap_set 函数。对此很困惑。
但是,这个列表非常有意义。我只有一个节点,它在一个 for 循环中。我没有更改变量名,因此指针都指向同一个节点,并且该节点在循环的每次迭代中都会更改它包含的字符串。
所以,我想知道如何解决这个问题。
我不能动态命名变量,我不能只创建一个动态的链表数组,因为我觉得那样会破坏散列 table 的目的。
我不知道我会使用哪种数据类型来存储它。
感谢任何帮助,谢谢!
将评论转化为答案——代码更易于阅读。
问题是,我认为,您不断将新值读入 val
(从 key
复制),但您只有一个变量。
在将字符串存储到哈希映射之前,您需要复制这些字符串。因此,查找 strdup()
函数并使用 strdup()
而不是 strcpy()
复制 key
中的字符串。将从 strdup()
返回的值分配给 word_node->final_word
.
如果不允许您使用 strdup()
,请编写您自己的变体:
char *dup_str(const char *str)
{
size_t len = strlen(str) + 1;
char *dup = malloc(len);
if (dup != 0)
memmove(dup, str, len);
return dup;
}
以下是我的代码的重要部分,无用部分已被注释掉:
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "hmap.h"
struct val_word{
char *final_word;
struct val_word* next;
};
int main (int argc, char **argv){
//Check if dictionary file is given
FILE *fp1;
char key [125];
char val [125];
char temp;
struct val_word *storage;
char c;
int i;
int j;
int l;
HMAP_PTR dictionary = hmap_create(0, 0.75);
fp1 = fopen(argv[1], "r");
do{
c = fscanf(fp1, "%s", key);
// Convert string to lowercase
strcpy(val, key);
//Alphabetically sort string
struct val_word* word_node = malloc(sizeof(struct val_word));
word_node->final_word = val;
word_node->next = NULL;
storage = hmap_get(dictionary, key);
if(storage == NULL){
hmap_set(dictionary, key, word_node);
}
else{
struct val_word *temp2 = storage;
while(temp2->next != NULL){
temp2 = temp2->next;
}
word_node->final_word = val;
word_node->next = NULL;
temp2->next = word_node;
hmap_set(dictionary, key, storage);
}
} while (c != EOF);
fclose(fp1);
while(storage->next != NULL){
printf("The list is %s\n", storage->final_word);
storage = storage->next;
}
return 0;
}
我得到了一个未知长度的字典文件,以及一个我无法触摸的散列 table 实现文件。散列 table 存储单词的混乱版本,键是单词按字母顺序排序的版本。例如:
部分词典包含:leloh, hello, elloh, holel
key 将是:ehllo
val就是一个链表,存储了上述4个词。
hmap_get 获取给定键的值,hmap_set 设置给定键的值。
我的代码处理一切正常,直到我尝试打印位于某个键的列表。 该列表将具有正确的大小,但仅存储作为输入的 LAST 值。因此,添加到上面的示例中,我的列表将是(按时间顺序):
- 乐乐
- 你好 -> 你好
- 洞 -> 洞 -> 洞
- ehllo -> ehllo -> ehllo -> ehllo
出于某种原因,它还将正确按字母顺序排列的字符串存储为最后一个字符串,我没有提供 hmap_set 函数。对此很困惑。
但是,这个列表非常有意义。我只有一个节点,它在一个 for 循环中。我没有更改变量名,因此指针都指向同一个节点,并且该节点在循环的每次迭代中都会更改它包含的字符串。
所以,我想知道如何解决这个问题。 我不能动态命名变量,我不能只创建一个动态的链表数组,因为我觉得那样会破坏散列 table 的目的。 我不知道我会使用哪种数据类型来存储它。
感谢任何帮助,谢谢!
将评论转化为答案——代码更易于阅读。
问题是,我认为,您不断将新值读入 val
(从 key
复制),但您只有一个变量。
在将字符串存储到哈希映射之前,您需要复制这些字符串。因此,查找 strdup()
函数并使用 strdup()
而不是 strcpy()
复制 key
中的字符串。将从 strdup()
返回的值分配给 word_node->final_word
.
如果不允许您使用 strdup()
,请编写您自己的变体:
char *dup_str(const char *str)
{
size_t len = strlen(str) + 1;
char *dup = malloc(len);
if (dup != 0)
memmove(dup, str, len);
return dup;
}