0

I have been on this for literal days, there is always a seg fault no matter what i do things i have tried:

  • debug 50: MULTIPLE TIMES, i fix the errors i find but end up with another one soon after, depending on the changes i make, the seg fault is at different places
  • check50: all the faces are red and frownng at me
  • valgrind shows no leaks
  • looked at other peoples solutions on github, did not help

i must be doing something wrong, i just dont know what, i am just going to share the entirety of my code here, so dont look if you are still working on this:

// Implements a dictionary's functionality

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

int load_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 = 65536;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // run word thru the hash function to obtain hash code and store in variable
    int index = hash(word);

    // assign cursor to point at the same address the first node at index is pointing at
    node *cursor = table[index];

    // stop when there is no more nodes to traverse
    while(cursor -> next != NULL)
    {
        // traverse linked list, comparing word with word in current node
        if (strcasecmp(word, cursor -> word) == 0)
        {
            return true;
        }
            // move to the next node in the linked list
            cursor = cursor -> next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    int sum = 0;

    //  stop at the end of the string
    for(int i = 0; word[i] != '\0'; i++)
    {
        // sum the ASCII value of each of the chars in the string
        sum += toupper(word[i]);
    }
    // return the hash code
    return sum % N;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{

    char buffer[LENGTH + 1];
    FILE *input;

    // open dictionary file
    if ((input = fopen(dictionary, "r")) == NULL)
    {
        // close file if pointer returns NULL
        fclose(input);
        return false;
    }
    // read input from dictionary file into buffer
    while(fscanf(input, "%s", buffer) != EOF)
    {
        // create node
        node *n = malloc(sizeof(node));
        if (n == NULL)
        {
            return false;
        }
        // copy string from buffer into node
        strcpy(n -> word, buffer);
        n -> next = NULL;

        // run buffer thru hash function to obtain hash code
        unsigned int hash_code = hash(buffer);

        // if location at hash table is empty, assign current node as first node
        if (table[hash_code] == NULL)
        {
            table[hash_code] = n;
        }
        // else insert node at the beginning of linked list
        else
        {
            n -> next = table[hash_code];
            table[hash_code] = n;
            load_count++;
        }
    }
    fclose(input);
    return true;
}

// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
    if (load_count > 0)
    {
        return load_count;
    }
    return 0;
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // create two temporary nodes
    node *temp, *cursor = malloc(sizeof(node));

    // loop thru entire array
    for (int i = 0; i < N; i++)
    {
        // assign temporary node to point at the same address the first node at current index is pointing at
        cursor = table[i];

        // loop thru linked list
        while(cursor -> next != NULL)
        {
            // assign both temporary nodes to point at the same node
            temp = cursor;

            // move one temporary node to the next node
            cursor = cursor -> next;

            // free the other temporary node
            free(temp);
        }
    }

    return true;
}
1
  • Hi jeddah. Having taken CS50 myself I remember that speller is the most difficult pset of the first part of the course. Would it be possible to better format the code section of your question? If memory serves, there are MANY moving parts, making your question a bit more difficult to answer. Thanks :) Apr 19, 2022 at 12:39

2 Answers 2

1

It's a common problem. ;-)

Look carefully at the unload() code. In particular, this line:

    while(cursor -> next != NULL)

Now, what happens if cursor itself is null? cursor->next doesn't exist! If it doesn't exist, the system will generate a seg fault because it can't find the variable struct element.

Think further about this line. Why is it checking cursor->next? Shouldn't it be checking cursor instead?

Of course, this doesn't address any other issues that may or may not exist (including a memory leak that I saw. ;-) )

Also, you might want to read the following post:

Do YOU know how to find a seg fault?? Advice to new programmers

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

0

allocating memory for each element of table ficed it for me

for(int i = 0; i < N; i++) { table[i] = malloc(sizeof(node)); }

I don't know why it works, please explain to me why it does if you find out

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .