简体   繁体   English

这个迷你HashMap有什么问题?

[英]What's wrong with this mini HashMap?

I am trying to implement a simple HashMap with only new get and insert functionalities. 我正在尝试仅使用new getinsert功能来实现简单的HashMap。 There's a very simple test function which is currently not passing. 有一个非常简单的测试函数,当前未通过。

The output: 输出:

test: Assertion `el == -10' failed.

When debugging the test, I get: 调试测试时,我得到:

key: hhh value: 300
key: aba value: 300

When it shuold be: 当它应该是:

key: hhh value: 10
key: aba value: -10

The code: 编码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include<assert.h>

#define N (1000)
#define MULTIPLIER (37)

typedef struct Node {
    char* key;
    int value;
    struct Node* next;
} Node;

typedef struct HashMap {
    Node* data[N];
} HashMap;

void test();

unsigned long hash(const char* key);
HashMap* new_hash_map();
void insert_element(char* key, int value, HashMap* hm);
int get_element(char* key, HashMap* hm, int* el);

unsigned long hash (const char* s)
{
    unsigned long h;
    unsigned const char* us;

    us = (unsigned const char*) s;

    h = 0;
    while (*us != '\0'){
    h = h * MULTIPLIER + *us;
    us++;
    }
    return h % N;
}

HashMap* new_hash_map()
{
    HashMap* hm = malloc(sizeof(HashMap));
    for (int i = 0; i < N; i++){
    hm->data[i] = NULL;
    }
    return hm;
}
void insert_element(char* key, int value, HashMap* hm)
{
    unsigned long hk = hash(key);
    Node* ll = hm->data[hk];
    if (ll == NULL) {
    ll = malloc(sizeof(Node));
    ll->key = key;
    ll->value = value;
    ll->next = NULL;
    return;
    }
    for (; ll != NULL; ll = ll->next){
    if (strcmp(ll->key, key) == 0){
        // already exists
        ll->value = value;
        return;
    }
    }
    // new element, same hash key
    ll->key = key;
    ll->value = value;
    ll->next = NULL;
}

int get_element(char* key, HashMap* hm, int* el)
{
    unsigned long hk = hash(key);
    Node* ll = hm->data[hk];
    if (ll == NULL) {
    return -1;
    }
    for (; ll != NULL; ll = ll->next){
    if (strcmp(ll->key, key) == 0){
        // already exists
        *el = ll->value;
        return 1;
    }
    }
    return -1;
}

void test()
{
    HashMap* hm = new_hash_map();
    int el;
    insert_element("aba", 10, hm);
    insert_element("hhhh", -10, hm);
    get_element("hhhh", hm, &el);
    assert(el == -10);
    get_element("aba", hm, &el);
    assert(el == 10);
}

int main () {
    test();
    return 0;
}

Well the primary problem is that you never inserted anything, You got prepared , allocated and then assigned to appropriate members and then you simply returned from the function. 好吧,主要的问题是您从不插入任何东西,您已经准备,分配,然后分配给适当的成员,然后从函数中返回。

Assign the allocated memory to hashmap s data .( hm->data[hk] = ll ). 将分配的内存分配给hashmapdata 。( hm->data[hk] = ll )。 Also check the return value of malloc . 还要检查malloc的返回值。

Also the second loop is quite misleading in that - you end up with NULL in ll and then you dereference it. 同样,第二个循环也很容易让人产生误解-在llNULL结尾,然后取消引用它。 You should allocate and do the same thing as you did before. 您应该分配并做与以前相同的事情。

   for (; ll != NULL; ll = ll->next){
    if (strcmp(ll->key, key) == 0){
        // already exists
        ll->value = value;
        return;
    }
    }
    // if the ll is NULL (in case it doesn't match) 
    // the you wil dereference NULL leading to UB.
    // new element, same hash key
    ll->key = key;
    ll->value = value;
    ll->next = NULL;

Dereferencing the NULL value is Undefined behavior. 取消引用NULL值是未定义行为。 Here the probable solution would be to allocate memory for this new node and then assign it to a slot in hashmap. 在这里,可能的解决方案是为此新节点分配内存,然后将其分配给哈希图中的插槽。

From standard 6.5.3.2p4 来自标准6.5.3.2p4

The unary * operator denotes indirection. 一元*运算符表示间接。 If the operand points to a function, the result is a function designator; 如果操作数指向一个函数,则结果为一个函数指示符;否则为0。 if it points to an object, the result is an lvalue designating the object. 如果它指向一个对象,则结果是一个指定该对象的左值。 If the operand has type ''pointer to type'', the result has type ''type''. 如果操作数的类型为“要键入的指针”,则结果的类型为“ type”。 If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined . 如果为指针分配了无效值,则一元*运算符的行为是undefined

On footnote 脚注

Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer , an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime. 一元*运算符用于取消对指针的引用无效值包括null指针 ,针对所指向对象的类型不适当地对齐的地址以及对象生命周期结束后的地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM