我正在尝试将(键,值)对添加到哈希图中,但是在插入后无法访问这些值。

每当发生冲突时,当我沿着每个哈希索引进行迭代时,此哈希表都应处理冲突。然后,在到达该索引的(键,值)对列表的末尾时,将其插入。

本质上,它是一个基本的链表哈希表。

问题是,当我再次尝试访问该值时,我一直遇到分段错误(并且我的showTable()函数也失败了)。在此测试中,我只是在尝试在每个哈希索引处添加了一些东西之后,尝试访问每个哈希索引处的第一对(键,值)。我做的事情可能很愚蠢,但我看到了。

我尚未评论,但我希望代码能自我解释。重要的一点是InsertKeyValuePair(),但是我添加了所有内容,因为代码审查也将是有益的。

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

typedef struct TVal KeyValue;

typedef struct TVal {
    char *value;
    char *key;
    KeyValue *next;
} KeyValue;

typedef KeyValue **HashTable;

int MAX_SIZE = 200;

int HashKey(char *Key, int Max);
void InsertKeyValuePair(char *key, char *value, int Index, HashTable table);
int insert(char *Key, char *value, HashTable table, int size);
void showTable(HashTable table, int size);

int HashKey(char *Key, int Max) {
    char c = *Key;
    int Hash = 0;
    int n = 1;

    while (c != 0) {
        Hash += n * ((int)c);
        c = *(Key + n);
        n++;
    }

    return Hash % MAX_SIZE;
}

void InsertKeyValuePair(char *key, char *value, int Index, HashTable table) {
    KeyValue *cursor = *(table + Index);
    while (cursor != NULL) {
        cursor = cursor->next;
    }
    cursor = malloc(sizeof(KeyValue));
    cursor->value = value;
    cursor->key = key;
    printf("insert <K,V>(%s,%s) HashIndex = %i\n", cursor->key, cursor->value, Index);

    //Trying to access value previously inserted
    KeyValue *cursor2 = *(table + Index);
    printf("<K,V>(%s,%s)\n", cursor2->key, cursor2->value);
}

int insert(char *Key, char *value, HashTable table, int size) {
    int Index = HashKey(Key, MAX_SIZE);
    InsertKeyValuePair(Key, value, Index, table);
    return size + 1;
}

void showTable(HashTable table, int size) {
    int i;
    for (i = 0; i < size; i++) {
        KeyValue *cursor = *(table + i);

        if (cursor == NULL)
            continue;

        while (cursor != NULL) {
            printf("==============");
            printf("<K,V>(%s,%s)\n", cursor->key, cursor->value);
            cursor = cursor->next;
        }
        printf("==============");
    }
}

int main() {
    HashTable HTbl = malloc(sizeof(HashTable) * MAX_SIZE);
    int size = 0;

    size = insert("yeuydfdan", "wesfg", HTbl, size);
    size = insert("ywere", "rdgg", HTbl, size);
    size = insert("ye4", "3244", HTbl, size);

    //showTable(HTbl, MAX_SIZE);
}

最佳答案

您的代码中存在多个问题:


哈希表未初始化为NULL,从而在尝试取消对其包含的指针的引用时导致分段错误。用calloc()分配将解决此问题。
将指针隐藏在typedef后面会造成混淆,并且容易出错。
main中的分配应为HashTable HTbl = calloc(sizeof(*HTbl), MAX_SIZE);
InsertKeyValuePair中的插入代码不会在哈希表存储桶列表的末尾或开头链接新对。
建议使用unsigned算术来计算哈希键,以避免溢出问题。
指针符号*(table + Index)令人困惑。您应该改为使用数组符号table[Index]
哈希表的长度(MAX_SIZE)和哈希表中的条目数(size)之间似乎有些混淆。适当重命名变量可以提高可读性。最好按地址传递计数并返回成功指示符。


这是更正的版本:

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

typedef struct TVal KeyValue;

typedef struct TVal {
    const char *value;
    const char *key;
    KeyValue *next;
} KeyValue;

typedef KeyValue **HashTable;

static unsigned int HASH_SIZE = 200;

static unsigned int HashKey(const char *key);
static KeyValue *InsertKeyValuePair(const char *key, const char *value, int index, HashTable table);
static int insert(const char *Key, const char *value, HashTable table, int *countp);
static void showTable(HashTable table);

static unsigned int HashKey(const char *key) {
    unsigned int hash = 0;
    size_t n;

    for (n = 0; key[n] != 0; n++) {
        hash += n * (unsigned char)key[n];
    }
    return hash % HASH_SIZE;
}

static KeyValue *InsertKeyValuePair(const char *key, const char *value, int index, HashTable table) {
    KeyValue *cursor;
    cursor = malloc(sizeof(KeyValue));
    if (cursor != NULL) {
        KeyValue **cursorp = &table[index];
        while (*cursorp != NULL) {
            cursorp = &(*cursorp)->next;
        }
        cursor->value = value;
        cursor->key = key;
        cursor->next = NULL;
        *cursorp = cursor;
    }
    return cursor;
}

static int insert(const char *key, const char *value, HashTable table, int *countp) {
    int index = HashKey(key);
    if (InsertKeyValuePair(key, value, index, table)) {
        *countp += 1;
        return 1;
    }
    return 0;
}

static void showTable(HashTable table) {
    unsigned int i;
    for (i = 0; i < HASH_SIZE; i++) {
        KeyValue *cursor = table[i];

        if (cursor == NULL)
            continue;

        while (cursor != NULL) {
            printf("==============");
            printf("<K,V>(%s,%s)\n", cursor->key, cursor->value);
            cursor = cursor->next;
        }
        printf("==============\n");
    }
}

int main() {
    HashTable HTbl = calloc(sizeof(*HTbl), HASH_SIZE);
    int count = 0;

    insert("yeuydfdan", "wesfg", HTbl, &count);
    insert("ywere", "rdgg", HTbl, &count);
    insert("ye4", "3244", HTbl, &count);

    showTable(HTbl);
    return 0;
}

关于c - 如何在C中正确使用指针,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57018519/

10-11 22:09
查看更多