I didn't do a deep dive, but something jumped out at me early. If this doesn't fix it, leave a comment and I'll look again.
Given that you're getting mostly correct results, its reasonable to assume that most of the code is working. So I'm immediately suspicious of the hash function. Now, look at this section of it:
int wordlength = strlen(word);
The load function works perfectly
I'm afraid I'm gonna have to disagree. You're calling malloc twice when the list is empty. So that's one node per list that you can effectively never free, as the pointer to that node is immediately orphaned.
As for the unload function. You problems are limited to this section:
struct node *current_table = table[i]; ...
The bug is in your unload function. You return after cleaning up just 1 list. But you have 26 of them to get through. The outer loop is also out of bounds. You iterate up to N + 1 for some reason.
// Unloads dictionary from memory, returning true if successful, else false
for (int i = 0; i < (N + 1); i++) // Out of bounds. Should ...
I'm sorry, but this code is not passing valgrind.
~/go/test/pset5/ $ valgrind ./speller small
==223== Memcheck, a memory error detector
==223== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==223== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==223== Command: ./speller small
Actually, your load() function is absolutely fine. The problem is your hash() unction. Your not normalising (%) the hash value by table length. which is why node->next = table[index]results in seg fault, because index > table length
When using fscanf do we need to iterate through what it is writing to the buffer to check for the null signifier so we can jump in and strcpy that buffer into our new node?
No. fscanf will just stop when it hits the null terminator. It also copies the null terminator.
Does strcpy automatically detect the NULL signifier and stop copying at that point?
The various branches are mutually exclusive. Only one of them will execute the way you've written it. But you want to free both the parents and the person.
And why check for NULL here?
else if(p->parents != NULL)
The parent will just be checked for NULL again once it is passed to free_family as a person.
Try to implement collatz function using recursion. Work it out for a single number and check if it's printing right number of steps.
If you have implemented this, most of the important stuff is done.
The next part would be to start a loop and store each number, along with number of steps it's taking (collatz algorithm), inside any data-structure (list, ...
My understanding is that list is a pointer variable initialised
without a value
No. It's initialized to NULL. That's what the = NULL part does. A variable can't be initialized without a value. Initializing means assigning a value. Uninitialized meaning memory is allocated, but you didn't write anything to it. Maybe this is what you meant, a pointer being ...