-1

I'm trying to learn how a hash table work but I'm running into a segmentation fault and I don't seem to be understanding the pointers where I load into my hash table.

I'm trying to get a dictionary of correctly spelled words into a hash table with an array of 26 nodes. My goal is to get each letter into its correct node.

I've spent almost 2 weeks on this problem. I've been moving pointers around to what I think is right but it is obviously not because it's not working. If someone could write this for my an explain what is going on I'll be able to see where I went wrong.

//Practice for my hash table
//I don't really inderstand what is going on in the cs50 version because there is just so much to look at so I am making my own.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int const LENGTH = 45;

typedef struct node {
    char word[LENGTH + 1];
    struct node *next;
} node;

loadHashTable(node **n, char c[]);

int main(int argc, char *argv[]){
    //Number of buckets for the hast table. 26 letters in the alphabit
    const unsigned int N = 26;
    //hash table
    node *table[N];

    //set everything to null in the table.
    for (int i = 0; i < N; i++)
    {
        table[N] = NULL;
    }
    
    //check for correct usage
    if (argc != 2)
    {
        printf("Usage: hashTable DICTIONARY\n");
        return 1;
    }
    
    //open a file
    char *fileName = argv[1];
    FILE *dictionaryFile = fopen(fileName, "r");
    if (!dictionaryFile)
    {
        printf("Can not open file: %s\n", argv[1]);
    }
    //read each line
    const unsigned MAX_LENGTH = 256;
    char buffer[MAX_LENGTH];
    while (fgets(buffer, MAX_LENGTH, dictionaryFile))
    {
        //change the word to lower case. Could I be doing this better?
        char lowerBuffer[MAX_LENGTH];
        for (int i = 0; i < MAX_LENGTH; i++)
        {
            char ch;
            ch = buffer[i];
            lowerBuffer[i] = (char) tolower(ch);
        }
    
        //load each line to table in correct bucket
        const int REDUCE_TO_BUCKET = 97;
        int correctBucket = lowerBuffer[0] - REDUCE_TO_BUCKET;
        loadHashTable(&table[correctBucket], lowerBuffer);
    }

    if (feof(dictionaryFile))
    {
        printf("\nEnd of File\n");
    }

    //TODO Print the hashtable
    //printHashTable(table[0]);
    printf("%s", *table[0]->word);
    //TODO Unload the hashtable

    fclose(dictionaryFile);
    return 0;
}

loadHashTable(node **n, char c[]){
    if (n == NULL)
    {
        //create temp node
        node *temp= malloc(sizeof(node));
        if (!temp)
        {
            printf("Could not create node.\n");
            return 1;
        }
        sprintf(temp->word, c);//load the word into the temp node
        temp->next = NULL;
        *n = temp;//Why is n not being set here? 
        printf("New Node Word: %s", (*n)->word);
   }
   else // we never get here. Why?
   {
        printf("Link Node: %s", (*n)->word);
        loadHashTable((*n)->next, c);
   }
}

printHashTable(node *toPrint){
    //TODO: Print the hash table
    if (toPrint->word)
        {
            printf("%s\n", toPrint->word);
            printHashTable(toPrint->next);
        }    
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Funlamb
  • 551
  • 7
  • 20
  • What is the exact line of code that triggers the seg fault? That can be found using a debugger. – kaylum Oct 29 '21 at 20:49
  • You don't need `lower_buffer`, you can modify `buffer` in place. The loop should stop at `strlen(buffer)`. – Barmar Oct 29 '21 at 20:50
  • You should remove the newline from `buffer`. See https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input – Barmar Oct 29 '21 at 20:50
  • `printf("%s", *table[0]->word);` needs to be `printf("%s", table[0]->word);` – kaylum Oct 29 '21 at 20:52
  • Don't hard-code ASCII codes, use `const int REDUCE_TO_BUCKET = 'a';` – Barmar Oct 29 '21 at 20:52
  • 1
    `if (n == NULL)` should be `if (*n == NULL)` – kaylum Oct 29 '21 at 20:54
  • `n == NULL` is wrong, that should had been `*n == NULL`. – Ext3h Oct 29 '21 at 20:54
  • `loadHashTable((*n)->next, c);` should be `loadHashTable(&((*n)->next), c);`. The type of the first arg is wrong and the compiler should give you a warning for that. Read and fix all compiler warnings. – kaylum Oct 29 '21 at 20:55
  • @kaylum I can't seem to find where the seg fault is triggered. All I get is `paused on exception` in the VSCode call stack. I can't push through it. – Funlamb Oct 29 '21 at 21:33
  • @Barmar Is it as easy as `for(int i = 0; i < strlen(buffer); i++) buffer[i] = tolower(buffer[i]);` ? – Funlamb Oct 29 '21 at 21:39
  • With all the suggestion you guys made it works. The problem is I don't understand it. Can I put up the changes and have you guys look at it and explain each line? – Funlamb Oct 29 '21 at 21:47

1 Answers1

0
void loadHashTable(node **n, char c[]){
    if (*n == NULL) //Why does this need to be *n and not n?
    {
        //create temp node
        node *temp= malloc(sizeof(node));
        if (!temp)
        {
            printf("Could not create node.\n");
        }
        sprintf(temp->word, "%s",  c);//load the word into the temp node
        temp->next = NULL;
        *n = temp;//This sets the *n to temp
        printf("New Node Word: %s", (*n)->word);
   }
   else // we never get here. Why?
   {
        printf("Link Node: %s", (*n)->word);
        loadHashTable(&((*n)->next), c);//What is the &((*n)->next) doing here? Specifically the '&'
   }
}
Funlamb
  • 551
  • 7
  • 20