Problem with not existing element in Hash Table in C

97 Views Asked by At

I have a problem with searching for elements in a simple array in C. As long as the element exists, there is no issue, but when I try to search for a non-existent element in the 'search' function within the line: struct node* bucketHead = mp->arr[bucketIndex]; the node pointer does not point to null, and the compiler shows a memory read error. How can I fix this?

below the fragment of code:

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

// Linked List node
struct node {

    // key is string
    char* key;

    // value is also string
    char* value;
    struct node* next;
};

// like constructor
void setNode(struct node* node, char* key, char* value)
{
    node->key = key;
    node->value = value;
    node->next = NULL;
    return;
};

struct hashMap {

    // Current number of elements in hashMap
    // and capacity of hashMap
    int numOfElements, capacity;

    // hold base address array of linked list
    struct node** arr;
};

// like constructor
void initializeHashMap(struct hashMap* mp)
{

    // Default capacity in this case
    mp->capacity = 100;
    mp->numOfElements = 0;

    // array of size = 1
    mp->arr = (struct node**)malloc(sizeof(struct node*)* mp->capacity);
    return;
}

int hashFunction(struct hashMap* mp, char* key)
{
    int bucketIndex;
    int sum = 0, factor = 31;
    for (int i = 0; i < strlen(key); i++) {

        // sum = sum + (ascii value of
        // char * (primeNumber ^ x))...
        // where x = 1, 2, 3....n
        sum = ((sum % mp->capacity)
            + (((int)key[i]) * factor) % mp->capacity)
            % mp->capacity;

        // factor = factor * prime
        // number....(prime
        // number) ^ x
        factor = ((factor % INT16_MAX)
            * (31 % INT16_MAX))
            % INT16_MAX;
    }

    bucketIndex = sum;
    return bucketIndex;
}

void insert(struct hashMap* mp, char* key, char* value)
{

    // Getting bucket index for the given
    // key - value pair
    int bucketIndex = hashFunction(mp, key);
    struct node* newNode = (struct node*)malloc(

        // Creating a new node
        sizeof(struct node));

    // Setting value of node
    setNode(newNode, key, value);

    // Bucket index is empty....no collision
    if (mp->arr[bucketIndex] == NULL) {
        mp->arr[bucketIndex] = newNode;
    }

    // Collision
    else {

        // Adding newNode at the head of
        // linked list which is present
        // at bucket index....insertion at
        // head in linked list
        newNode->next = mp->arr[bucketIndex];
        mp->arr[bucketIndex] = newNode;
    }
    return;
}

char* search(struct hashMap* mp, char* key)
{

    // Getting the bucket index
    // for the given key
    int bucketIndex = hashFunction(mp, key);

    // Head of the linked list
    // present at bucket index
    struct node* bucketHead = mp->arr[bucketIndex];
    while (bucketHead != NULL) {

        // Key is found in the hashMap
        if (strcmp(bucketHead->key, key) == 0) {
            return bucketHead->value;
        }
        bucketHead = bucketHead->next;
    }

    // If no key found in the hashMap
    // equal to the given key
    //char* errorMssg = (char*)malloc(sizeof(char) * 25);
    //errorMssg = "";
    char err[] = "No data found.\n";
    return err;
}

// Drivers code
int main()
{
    char key1[] = "32:86:74:66:f6:7d"; char val1[] = "Number1";
    char key2[] = "43:b0:9f:42:55:9b"; char val2[] = "Number3";
    char key3[] = "a4:c1:38:46:7c:58"; char val3[] = "Numebr4";
    char key4[] = "a4:c1:38:46:7c:59";

    ;

    // Initialize the value of mp
    struct hashMap* mp
        = (struct hashMap*)malloc(sizeof(struct hashMap));
    initializeHashMap(mp);

    insert(mp, key1, val1);
    insert(mp, key2, val2);
    insert(mp, key3, val3);

    printf("%s\n", search(mp, key1));
    

    // Key is not inserted
    printf("%s\n", search(mp, key4));



    return 0;
}
1

There are 1 best solutions below

0
David Ranieri On

That's because mp->arr[bucketIndex] returns an uninitialized element of the array, switch from malloc to calloc to get NULL:

mp->arr = calloc(mp->capacity, sizeof(struct node *));

Also note that this returns a dangling pointer:

char err[] = "No data found.\n";
return err;

Which could be easily fixed:

char *err = "No data found.\n";
return err;