-2

Just trying to get the simple version of the hash function to work for now (haven't implemented the hash function logic yet, just wanna fix the memory errors before getting to the actual logic) but can't figure where the memory error is arising.

In my load function, I open up the dictionary file and initialize my hash table to set all pointers to NULL. Then, I use fscanf to scan the dictionary file, create a node *n for each word in the dictionary, and copy the word into this node.

If table[index] == NULL, then I set both table[index] and a node called head equal to node n, and set the next address equal to NULL. Otherwise, I set the next node as table[index] and table[index] as the current node, n.

// Implements a dictionary's functionality

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "dictionary.h"

//represents the number of words in the dictionary
int word_count = 0;

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

// TODO: Choose number of buckets in hash table
const unsigned int N = 26;

// Hash table
node *table[N];

// initialize hash table (set all values to NULL)
// reference video: https://youtu.be/2Ti5yvumFTU
void init_table()
{
    for (int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }
}

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    //obtain the index of the word in the hash
    int node_index = hash(word);

    //initiate cursor to point to the first node of the LL
    node *cursor = table[node_index];

    //traverse through the LL searching for the word
    while (cursor != NULL)
    {
        if (strcasecmp(cursor->word, word) == 0)
        {
            return true;
        }
        cursor = cursor->next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function
    return ((toupper(word[0]) - 'A') % N);
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    char *word = NULL;
    int node_index = 0;

    // Open input file
    FILE *file = fopen(dictionary, "r");

    //check if file exists
    if (file == NULL)
    {
        return false;
    }

    init_table();

    //count the number of words in the dictionary
    word_count = fscanf(file, "%s", word);

    node *head;

    //loop through file for each word
    while (word_count != EOF)
    {
        //assign memory for a new node
        node *n = malloc(sizeof(node));
        if (n == NULL)
        {
            return false;
        }

        //copy the scanned word into the created node
        strcpy(n->word, word);

        //get the hash index of the node
        node_index = hash(n->word);

        if (table[node_index] == NULL)
        {
            head = table[node_index] = n;
            n->next = NULL;
        }
        // otherwise set next node as table[index], table[index] as current node n
        else
        {
            n->next = head;
            table[node_index] = n;
        }
    }
    return true;
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    for (int i = 0; i < N; i++)
    {
        node *cursor = table[i];
        node *temp = table[i];

        while (cursor != NULL)
        {
            cursor = cursor->next;
            free(temp);
            temp = cursor->next;
        }
    }
    return true;
}

A different file has the main function that links to this file.

Any help would be appreciated, thanks!

Sam
  • 105
  • 2
  • 11
  • There is no `main` in this program. – Eugene Sh. Jun 03 '22 at 14:26
  • Its actually in a different file – Sam Jun 03 '22 at 14:27
  • 2
    You need to post [mcve]. Do not ignore the *minimal* part of it too. – Eugene Sh. Jun 03 '22 at 14:29
  • I've removed the boilerplate main file containing the main function that links to this file. Also removed the unnecessary functions in this code – Sam Jun 03 '22 at 14:33
  • 1
    Have you tried running your code line by line in a debugger while monitoring the values of all variables, in order to determine in which line your program stops behaving as intended? If you did not try this, then you may want to read this: [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/12149471) You may also want to read this: [How to debug small programs?](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) Note that CS50 has its own debugger, which is called "debug50". – Andreas Wenzel Jun 03 '22 at 14:54
  • 1
    Even if using a debugger does not actually solve the problem, it should at least help you to isolate the problem and to create a [mre] of the problem, so that it will be easier for other people to help you. Most people will not be willing to debug your whole program for you, [as that should be your job](https://idownvotedbecau.se/nodebugging/). – Andreas Wenzel Jun 03 '22 at 14:56
  • 1
    Questions seeking debugging help should generally provide a [mre] of the problem, which includes a function `main` and all `#include` directives. This allows other people to easily test your program, by simply using copy&paste. – Andreas Wenzel Jun 03 '22 at 14:56
  • Great I'll try using a debugger – Sam Jun 03 '22 at 17:19
  • I was able to use a debugger and the fix the problem. The problem stemmed from the string 'word' becoming inaccessible after initialising it as NULL. Using word[LENGTH + 1] seemed to have fixed it. – Sam Jun 06 '22 at 15:54

1 Answers1

0

Your unload() function is buggy. For example, in the following statement you have no guarantee that cursor will not be null:

        temp = cursor->next;

You can pretty easily fix this by changing the body of the loop to be:

        temp = cursor;
        cursor = cursor->next;
        free(temp);
Tim Boddy
  • 1,019
  • 7
  • 13
  • Thanks for the suggestion. I did try it but the segmentation error persists – Sam Jun 03 '22 at 14:53
  • That means that your original code had more than one error. Posting a Minimal Reproducible Example as suggested by Eugene Sh would be one good way to proceed. From the perspective of improving your skill at coding and debugging, Andreas Wenzel's suggestion would be even better. – Tim Boddy Jun 03 '22 at 15:09