Ха sh ключ таблицы не работает из-за последнего ввода - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь создать табличную программу ha sh, которая может вводить ключ ha sh и строковые данные, которые будут храниться в таблице ha sh. Все хорошо, кроме «Menu == 2», каждый раз, когда я пытаюсь найти строковые данные, вводя ключ ha sh, один (последний позиционированный) ключ ha sh в таблице изменяется на то, что я ввел в "Menu == 2".

Вот таблица ha sh из "Menu == 4" с функцией viewAll () (после ввода ключей ha sh и строковых данных через "Menu = = 1 "):

//FORMAT:
//[index]: [key] (string data) -> [key] (string data) -> ..

--------------------------------------------------------------------------------

//after I finished inputting all hash keys and string datas through menu 1  

[0]: 0 (INDIA) -> 97 (PAKISTAN) -> 194 (BURMA) -> 291 (AFGHANISTAN)
[1]: 1 (UNITED STATES) -> 98 (CANADA) -> 195 (MEXICO) -> 292 (PANAMA)
[2]: 2 (THE NETHERLANDS) -> 99 (LUXEMBOURG) -> 196 (BELGIUM) -> 293 (FRANCE)
[3]: 3 (SYRIA) -> 100 (LEBANON) -> 197 (ISRAEL) -> 294 (BAHRAIN)

//this hash table is correct

--------------------------------------------------------------------------------

after menu 2 (last key inputted on menu 2 was 0)

[0]: 0 (INDIA) -> 97 (PAKISTAN) -> 194 (BURMA) -> 291 (AFGHANISTAN)
[1]: 1 (UNITED STATES) -> 98 (CANADA) -> 195 (MEXICO) -> 292 (PANAMA)
[2]: 2 (THE NETHERLANDS) -> 99 (LUXEMBOURG) -> 196 (BELGIUM) -> 293 (FRANCE)
[3]: 3 (SYRIA) -> 100 (LEBANON) -> 197 (ISRAEL) -> 0 (BAHRAIN)

//(why is BAHRAIN key 0, it should be 294)

--------------------------------------------------------------------------------

after menu 2 (last key inputted on menu 2 was 99)

[0]: 0 (INDIA) -> 97 (PAKISTAN) -> 194 (BURMA) -> 291 (AFGHANISTAN)
[1]: 1 (UNITED STATES) -> 98 (CANADA) -> 195 (MEXICO) -> 292 (PANAMA)
[2]: 2 (THE NETHERLANDS) -> 99 (LUXEMBOURG) -> 196 (BELGIUM) -> 293 (FRANCE)
[3]: 3 (SYRIA) -> 100 (LEBANON) -> 197 (ISRAEL) -> 99 (BAHRAIN)

//(why is BAHRAIN key 99, it should be 294)

Как видите, это всегда последний позиционируемый объект, который будет изменен в меню ввода 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;
}

Можно ли как-нибудь это исправить? И заранее извините, что мой код неаккуратен и ужасен для чтения.

1 Ответ

2 голосов
/ 24 марта 2020

Это происходит потому, что каждый раз, когда вы звоните pu sh, вы выделяете новую память и сохраняете указатель на эту память в узле :

    node = (struct data*) malloc(sizeof(struct data));

После этого эти выделенные данные вставляются в таблицу, но узел все еще указывает на эти данные. И затем, когда вы запускаете viewStrData , вы делаете узел-> ключ = ключ , и узел в этот момент все еще указывает на данные, которые были в последний раз вставлены, когда вы называется пу sh. Вот почему каждый раз, когда вы вызываете 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;
    }
}

PS В этой строке есть опечатка:

        } else if (menu = 4) {

это должно быть == вместо = . В настоящее время, если меню не 1, 2 или 3, оно будет назначать ему 4 внутри оператора if, и результат 4 будет true каждый раз. Таким образом, даже если вы введете 7, меню будет перезаписано на 4 и будет вызвано viewAll .

...