C 哈希表';s键由于上次输入而出错

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()函数

我正在尝试创建一个哈希表程序,它可以输入一个哈希键和一个字符串数据,这些数据将存储在哈希表中。一切正常,除了“Menu==2”中,每次我试图通过输入哈希键来搜索字符串数据时,表中的一个(最后定位的)哈希键都会更改为我在“Menu==2”中输入的值

下面是“Menu==4”中带有
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
不应对数据进行任何更改。你看到这个函数中的任何语句了吗?没有,反正我也不会马上注意到。我想这和一个迟滞的缓冲区输入有关?你怎么看<