C 哈希表';s键由于上次输入而出错
我正在尝试创建一个哈希表程序,它可以输入一个哈希键和一个字符串数据,这些数据将存储在哈希表中。一切正常,除了“Menu==2”中,每次我试图通过输入哈希键来搜索字符串数据时,表中的一个(最后定位的)哈希键都会更改为我在“Menu==2”中输入的值 下面是“Menu==4”中带有C 哈希表';s键由于上次输入而出错,c,hash,linked-list,hashtable,doubly-linked-list,C,Hash,Linked List,Hashtable,Doubly Linked List,我正在尝试创建一个哈希表程序,它可以输入一个哈希键和一个字符串数据,这些数据将存储在哈希表中。一切正常,除了“Menu==2”中,每次我试图通过输入哈希键来搜索字符串数据时,表中的一个(最后定位的)哈希键都会更改为我在“Menu==2”中输入的值 下面是“Menu==4”中带有viewAll()函数的哈希表(在我通过“Menu==1”输入哈希键和字符串数据之后): 如您所见,它总是最后一个被输入菜单2更改的位置 下面是源代码,为了不浪费您的时间,我将查看void viewStrData()函数
viewAll()
函数的哈希表(在我通过“Menu==1”输入哈希键和字符串数据之后):
如您所见,它总是最后一个被输入菜单2更改的位置
下面是源代码,为了不浪费您的时间,我将查看void viewStrData()
函数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct data {
int key;
char strData [100];
struct data *next;
}*head [97], *tail [97], *node, *curr;
//index location within hash table = key % 97
int hashing (int key) {
int result = key % 97;
return result;
}
//input key and strData, push it to hash table
void push (int key, char strData [100]) {
node = (struct data*) malloc(sizeof(struct data));
node->key = key;
strcpy (node->strData, strData);
node->next = NULL;
int idx = hashing (key);
if (!head [idx]) {
head [idx] = tail [idx] = node;
} else {
tail [idx]->next = node;
tail [idx] = node;
}
}
//see strData based on key
void viewStrData (int key) {
curr = head [hashing (key)];
node->key = key;
while (true) {
if (curr->key == node->key) {
printf ("[%s]\n", curr->strData);
break;
} else {
curr = curr->next;
}
}
}
//print out current hash table
void viewAll () {
for (int i = 0; i < 97; i++) {
printf ("[%d]: ", i);
if (!head [i]) {
printf ("-\n");
} else {
curr = head [i];
while (curr) {
if (curr == head [i]) {
printf ("%d", curr->key);
printf (" (%s)", curr->strData);
} else {
printf (" -> %d", curr->key);
printf (" (%s)", curr->strData);
}
curr = curr->next;
}
printf ("\n");
}
}
}
int main () {
int menu, key;
char strData [100];
while (true) {
printf ("=======================================\n");
printf ("MENU [1-3]: \n");
printf ("1. INPUT DATA\n");
printf ("2. SEARCH DATA\n");
printf ("3. EXIT\n");
printf ("=======================================\n");
scanf ("%d", &menu);
if (menu == 1) {
printf ("ENTER KEY AND STRING DATA: \n");
scanf ("%d %[^\n]", &key, strData);
push (key, strData);
printf ("HASH TABLE UPDATED!\n");
} else if (menu == 2) {
printf ("ENTER KEY TO FIND STRING DATA: \n");
scanf ("%d", &key);
printf ("STRING DATA OF KEY [%d] IS: ", key);
viewStrData (key);
} else if (menu == 3) {
printf ("PROGRAM EXITED\n");
break;
} else if (menu = 4) {
viewAll ();
}
}
return 0;
}
#包括
#包括
#包括
结构数据{
int键;
char strData[100];
结构数据*下一步;
}*头[97],*尾[97],*节,*电流;
//哈希表中的索引位置=键%97
整数散列(整数键){
int结果=键%97;
返回结果;
}
//输入键和strData,将其推送到哈希表
无效推送(int键,char strData[100]){
node=(结构数据*)malloc(sizeof(结构数据));
节点->键=键;
strcpy(节点->strData,strData);
节点->下一步=空;
int idx=散列(键);
如果(!头[idx]){
头[idx]=尾[idx]=节点;
}否则{
tail[idx]->next=节点;
tail[idx]=节点;
}
}
//请参阅基于密钥的strData
void viewStrData(int键){
curr=头[散列(键)];
节点->键=键;
while(true){
如果(当前->键==节点->键){
printf(“[%s]\n”,curr->strData);
打破
}否则{
当前=当前->下一步;
}
}
}
//打印当前哈希表
void viewAll(){
对于(int i=0;i<97;i++){
printf(“[%d]:”,i);
如果(!头[i]){
printf(“-\n”);
}否则{
curr=头[i];
while(curr){
如果(curr==头[i]){
printf(“%d”,当前->键);
printf((%s)”,curr->strData);
}否则{
printf(“->%d”,当前->键);
printf((%s)”,curr->strData);
}
当前=当前->下一步;
}
printf(“\n”);
}
}
}
int main(){
int菜单,按键;
char strData[100];
while(true){
printf(“==========================================================\n”);
printf(“菜单[1-3]:\n”);
printf(“1.输入数据\n”);
printf(“2.搜索数据\n”);
printf(“3.退出\n”);
printf(“==========================================================\n”);
scanf(“%d”,菜单(&M);
如果(菜单==1){
printf(“输入键和字符串数据:\n”);
scanf(“%d%[^\n]”,&key,strData);
按(键,标准数据);
printf(“哈希表更新!\n”);
}否则如果(菜单==2){
printf(“输入键以查找字符串数据:\n”);
scanf(“%d”和键)(&key);
printf(“键[%d]的字符串数据为:”,键);
viewStrData(键);
}否则如果(菜单==3){
printf(“程序已退出\n”);
打破
}否则如果(菜单=4){
viewAll();
}
}
返回0;
}
我有办法解决这个问题吗?在此之前,我很抱歉,我的代码太草率,读起来很糟糕。这是因为每次调用推送时,都会分配新内存并将指向该内存的指针存储在节点中:
node = (struct data*) malloc(sizeof(struct data));
之后,该分配的数据被插入到表中,但节点仍然指向该数据。然后,当您运行viewStrData时,您会执行node->key=key,此时节点仍然指向上次调用push时插入的数据。这就是为什么每次调用viewStrData时,最后插入的节点密钥都会更新为接收到的密钥
我建议直接比较收到的密钥,如下所示:
void viewStrData (int key) {
curr = head [hashing (key)];
// node->key = key; <-- No need for this
while (true) {
if (curr->key == key) { // <-- compare key directly, instead of storing it into node->key
printf ("[%s]\n", curr->strData);
break;
} else {
curr = curr->next;
}
}
它应该是=而不是=。当前,如果菜单不是1、2或3,它将在if语句中为其分配4,并且每次4的结果都是true。因此,即使您在此处输入7,菜单也将被4覆盖,并且将调用viewAll。这是因为每次调用push时,您都会分配新内存并将指向该内存的指针存储在节点中:
node = (struct data*) malloc(sizeof(struct data));
之后,该分配的数据被插入到表中,但节点仍然指向该数据。然后,当您运行viewStrData时,您会执行node->key=key,此时节点仍然指向上次调用push时插入的数据。这就是为什么每次调用viewStrData时,最后插入的节点密钥都会更新为接收到的密钥
我建议直接比较收到的密钥,如下所示:
void viewStrData (int key) {
curr = head [hashing (key)];
// node->key = key; <-- No need for this
while (true) {
if (curr->key == key) { // <-- compare key directly, instead of storing it into node->key
printf ("[%s]\n", curr->strData);
break;
} else {
curr = curr->next;
}
}
它应该是=而不是=。当前,如果菜单不是1、2或3,它将在if语句中为其分配4,并且每次4的结果都是true。因此,即使在此处输入7,菜单也将被4覆盖,并调用viewAll。
viewStrData
不应对数据进行任何更改。你看到这个函数中的任何语句了吗?没有,反正我也不会马上注意到。我想这与一个迟滞的缓冲区输入有关。你认为node->key=key
正在做什么?viewStrData
不应对数据进行任何更改。你看到这个函数中的任何语句了吗?没有,反正我也不会马上注意到。我想这和一个迟滞的缓冲区输入有关?你怎么看<