如何在带有链表的哈希表中修复 C 中的分段错误

问题描述

我正在编写一个哈希表,该表将字符串映射到整数,该整数具有指向链表节点的指针的数组。似乎我在设置值方法中遇到了分段错误,我正在比较字符串以查看特定键是否已在哈希表中。

typedef struct _node
{
    char *key;
    int value;
    struct _node *next; /* pointer to the next node in the list */
} node;

/*
 * Declaration of the hash table struct.
 * 'slot' is an array of node pointers,so it's a pointer to a pointer.
 */

typedef struct
{
    node **slot;
} hash_table;


int hash(char *s)
{
    int sum,size,i;
    sum = 0;
    size = strlen(s);
    for (i = 0; i < size; i++)
    {
        sum += (int) s[i];
    }
    return (sum % SIZE_ARRAY);
}


node *create_node(char *key,int value)
{
    node *result = (node *)malloc(sizeof(node));

    if (result == NULL)
    {
        fprintf(stderr,"Fatal error: out of memory. "
                "Terminating program.\n");
        exit(1);
    }

    result->key = key;
    result->value = value;
    result->next = NULL;

    return result;
}

/* Create a new hash table. */
hash_table *create_hash_table()
{
    hash_table *table = (hash_table *)malloc(sizeof(hash_table));
    if (table == NULL)
    {
        fprintf(stderr,"Fatal error: out of memory. "
                "Terminating program.\n");
        exit(1);
    }
    table->slot = (node **)calloc(SIZE_ARRAY,sizeof(node *));
    if (table->slot == NULL)
    {
        fprintf(stderr,"Fatal error: out of memory. "
                "Terminating program.\n");
        exit(1);
    }
    return table;
}

void set_value(hash_table *ht,char *key,int value)
{
    int indx = hash(key);
    int found = 0;
    node *new_node;
    node *list = ht->slot[indx];
    while (list != NULL)
    {
        if (strcmp(list->key,key) == 0)
        {
            found = 1;
            list->value = value;
        }
        list++;
    }
    if (found == 0)
    {
        new_node = create_node(key,value);
        new_node->next = ht->slot[indx];
        ht->slot[indx] = new_node;
    }
}

我使用gdp尝试调试,似乎错误来自“if (strcmp(list->key,key) == 0)”行,我认为它可能与指针有关但我不知道如何解决它。

解决方法

list++ 循环中的 while 是错误的。您想要:list = list->next 并且,在该循环中,在 if 下,您想要 break;

之后的 list->value = value;

你真的不需要found,因为你可以挂断list

这是一些重构的代码:

void
set_value(hash_table * ht,char *key,int value)
{
    int indx = hash(key);
    node *new_node;
    node *list = ht->slot[indx];

    while (list != NULL) {
        if (strcmp(list->key,key) == 0) {
            list->value = value;
            break;
        }
        list = list->next;
    }

    if (list == NULL) {
        new_node = create_node(key,value);
        new_node->next = ht->slot[indx];
        ht->slot[indx] = new_node;
    }
}