散列 table 值被覆盖的问题
Hash table problems with values getting overwritten
我第一次测试哈希 tables,我得到了一个奇怪的错误。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 40
typedef struct snode {
char *nome;
struct snode *next;
} TNode;
typedef TNode *TList;
typedef struct tht {
TList *buckets;
int nbuckets;
} THT;
TList Create_List();
TNode *Create_Node(char *);
TList Insert_List(TList, char *);
THT *Create_THT(int n);
void HT_Print(THT *ht);
THT *Insert_THT(THT *ht, char *name, int key);
int hash(char *name);
void Print_List(TList list);
int main() {
THT *ht = Create_THT(5);
char name[MAX];
int key, contr;
printf("INSERISCI 0 PER USCIRE O INSERIRE NOME \n");
do {
printf("\n INSERIRE NOME : ");
scanf("%s", &name); //AFTER THE SECOND INSERTION FROM THIS LANE VALUES CHANGE INSIDE ht?? why
key = hash(name);
ht = Insert_THT(ht, name, key);
printf("\n Inserisci 1 per continuare 0 per terminare ");
scanf("%d", &contr);
} while (contr != 0);
HT_Print(ht);
return 0;
}
TList Create_List() {
return NULL;
}
TNode *Create_Node(char nome[MAX]) {
TNode *node;
node = malloc(sizeof(TNode));
node->nome = nome;
node->next = NULL;
return node;
}
TList Insert_List(TList list, char info[MAX]) {
TNode *tmp;
TNode *node;
node = Create_Node(info);
tmp = list;
if (list == NULL) {
list = node;
} else {
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = node;
}
return list;
}
THT *Create_THT(int n) {
int i;
THT *ht = malloc(sizeof(THT));
ht->buckets = malloc(n * sizeof(TList));
for (i = 0; i < n; i++) {
ht->buckets[i] = Create_List();
}
ht->nbuckets = n;
return ht;
}
void HT_Print(THT *ht) {
int i;
for (i = 0; i < ht->nbuckets; i++) {
Print_List(ht->buckets[i]);
}
}
int hash(char *name) {
return (name[0] - 'a');
}
THT *Insert_THT(THT *ht, char name[MAX], int key) {
ht->buckets[key] = Insert_List(ht->buckets[key], name);
return ht;
}
void Print_List(TList list) {
while (list != NULL) {
printf("%s", list->nome);
list = list->next;
}
}
我用调试测试了它。第一次插入时没问题(例如我插入 adam
),但随后发生了一些奇怪的事情。
第二次,当我输入名称 bob
时(因为它就像一个名称词汇表),我检查了 ht->buckets
的值,里面有些东西发生了变化。
我不明白我什至没有进入有效修改我的散列 table (ht
) 中的内容的函数,并且它内部发生了变化。我快疯了,我试图找到一个解决方案,但我真的不明白如何从一个不必处理我的 HT 的结构值在该结构内发生变化的主命令...
无关,但使用英文名称和输出对每个人来说都更容易。
只是一个猜测,但在 Create_Node
中,您为新节点分配了内存,但没有为名称 (nome
) 分配内存。
您只需将指针复制到传递的数组,每次插入新名称时都会更改。为名称分配内存并复制内容而不是指针应该可以解决这个问题,例如
node->nome = strdup(nome);
不要忘记,当您在更大的上下文中使用哈希时,您最终必须清理哈希和名称,这意味着为节点和名称释放内存
free(node->nome);
free(node);
Create_Node
收到指向 main
中数组 name
的指针。每次输入新名称时都会重复使用此数组。这意味着,所有节点都指向同一个数组,因此所有节点都打印相同的(最后输入的)名称。
为每个节点分配单独的内存并将数组复制到此内存 (strdup
),解决了问题。
你的代码有很多问题:
- 您在
typedef TNode *TList;
中将指针隐藏在 typedef 后面,这很容易出错并且会让代码的读者感到困惑。
CreateNode
不会复制 name
指向的内存。鉴于您如何使用此函数,所有节点共享同一个数组,因此所有节点都具有相同的名称。使用node->nome = strdup(nome);
解决这个问题。
scanf("%s", &name);
不正确:&
是多余的,您应该指定要存储到 name
的最大字符数以避免缓冲区溢出。使用 scanf("%39s", name);
。此外,您应该测试 return 值以检测意外的文件结尾。
Print_List
不分隔名称。使用 printf("%s\n", list->nome)
将它们分行输出。
- 您应该在程序结束时释放散列 table:
void Free_THT(THT *ht) {
if (ht) {
int i;
for (i = 0; i < ht->nbuckets; i++) {
TNode *list = ht->buckets[i];
ht->buckets[i] = NULL;
while (list != NULL) {
TNode *node = list;
list = list->next;
free(node->name);
free(node);
}
}
free(ht->buckets);
free(ht);
}
}
我第一次测试哈希 tables,我得到了一个奇怪的错误。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 40
typedef struct snode {
char *nome;
struct snode *next;
} TNode;
typedef TNode *TList;
typedef struct tht {
TList *buckets;
int nbuckets;
} THT;
TList Create_List();
TNode *Create_Node(char *);
TList Insert_List(TList, char *);
THT *Create_THT(int n);
void HT_Print(THT *ht);
THT *Insert_THT(THT *ht, char *name, int key);
int hash(char *name);
void Print_List(TList list);
int main() {
THT *ht = Create_THT(5);
char name[MAX];
int key, contr;
printf("INSERISCI 0 PER USCIRE O INSERIRE NOME \n");
do {
printf("\n INSERIRE NOME : ");
scanf("%s", &name); //AFTER THE SECOND INSERTION FROM THIS LANE VALUES CHANGE INSIDE ht?? why
key = hash(name);
ht = Insert_THT(ht, name, key);
printf("\n Inserisci 1 per continuare 0 per terminare ");
scanf("%d", &contr);
} while (contr != 0);
HT_Print(ht);
return 0;
}
TList Create_List() {
return NULL;
}
TNode *Create_Node(char nome[MAX]) {
TNode *node;
node = malloc(sizeof(TNode));
node->nome = nome;
node->next = NULL;
return node;
}
TList Insert_List(TList list, char info[MAX]) {
TNode *tmp;
TNode *node;
node = Create_Node(info);
tmp = list;
if (list == NULL) {
list = node;
} else {
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = node;
}
return list;
}
THT *Create_THT(int n) {
int i;
THT *ht = malloc(sizeof(THT));
ht->buckets = malloc(n * sizeof(TList));
for (i = 0; i < n; i++) {
ht->buckets[i] = Create_List();
}
ht->nbuckets = n;
return ht;
}
void HT_Print(THT *ht) {
int i;
for (i = 0; i < ht->nbuckets; i++) {
Print_List(ht->buckets[i]);
}
}
int hash(char *name) {
return (name[0] - 'a');
}
THT *Insert_THT(THT *ht, char name[MAX], int key) {
ht->buckets[key] = Insert_List(ht->buckets[key], name);
return ht;
}
void Print_List(TList list) {
while (list != NULL) {
printf("%s", list->nome);
list = list->next;
}
}
我用调试测试了它。第一次插入时没问题(例如我插入 adam
),但随后发生了一些奇怪的事情。
第二次,当我输入名称 bob
时(因为它就像一个名称词汇表),我检查了 ht->buckets
的值,里面有些东西发生了变化。
我不明白我什至没有进入有效修改我的散列 table (ht
) 中的内容的函数,并且它内部发生了变化。我快疯了,我试图找到一个解决方案,但我真的不明白如何从一个不必处理我的 HT 的结构值在该结构内发生变化的主命令...
无关,但使用英文名称和输出对每个人来说都更容易。
只是一个猜测,但在 Create_Node
中,您为新节点分配了内存,但没有为名称 (nome
) 分配内存。
您只需将指针复制到传递的数组,每次插入新名称时都会更改。为名称分配内存并复制内容而不是指针应该可以解决这个问题,例如
node->nome = strdup(nome);
不要忘记,当您在更大的上下文中使用哈希时,您最终必须清理哈希和名称,这意味着为节点和名称释放内存
free(node->nome);
free(node);
Create_Node
收到指向 main
中数组 name
的指针。每次输入新名称时都会重复使用此数组。这意味着,所有节点都指向同一个数组,因此所有节点都打印相同的(最后输入的)名称。
为每个节点分配单独的内存并将数组复制到此内存 (strdup
),解决了问题。
你的代码有很多问题:
- 您在
typedef TNode *TList;
中将指针隐藏在 typedef 后面,这很容易出错并且会让代码的读者感到困惑。 CreateNode
不会复制name
指向的内存。鉴于您如何使用此函数,所有节点共享同一个数组,因此所有节点都具有相同的名称。使用node->nome = strdup(nome);
解决这个问题。scanf("%s", &name);
不正确:&
是多余的,您应该指定要存储到name
的最大字符数以避免缓冲区溢出。使用scanf("%39s", name);
。此外,您应该测试 return 值以检测意外的文件结尾。Print_List
不分隔名称。使用printf("%s\n", list->nome)
将它们分行输出。- 您应该在程序结束时释放散列 table:
void Free_THT(THT *ht) {
if (ht) {
int i;
for (i = 0; i < ht->nbuckets; i++) {
TNode *list = ht->buckets[i];
ht->buckets[i] = NULL;
while (list != NULL) {
TNode *node = list;
list = list->next;
free(node->name);
free(node);
}
}
free(ht->buckets);
free(ht);
}
}