You can jump to **SUGGESTION #1** for quick answer on wrong number of misspelled words.

You can jump to **SUGGESTION #2** for quick answer memory leaks.

I am still working on the memory leaks. However, I found why your number of misspelled words don't match the staff's implementation.

Line 54:

    current->is_word = false;

You do not want to change any variables' values in your trie under the `check()` function. You only want to read data on `check()`, not write (or overwrite).

While debugging I found that "not" is a word that your speller marks as misspelled.

I tested with a dictionary that has only one line:

    not

And a text that has three lines:

    not
    nothing
    not

The speller would take the first not as correctly spelled and second one as misspelled. Why?

Because line 54 is setting `not`'s boolean to false if the next node is `NULL`. It does this while evaluating the word `nothing`.

**SUGGESTION #1**

Delete line 54. You can `return false` as you are already doing, but you don't want to edit anything on the `check()` function. It will look something like this:

    bool check(const char* word)
    {
        // TODO
        node* current = root;
        int w_index;
    
        int w_len = strlen(word);
        for(int i = 0; i < w_len; i++)
        {
    
            if(isalpha(word[i]))
            {
                if(isupper(word[i]))
                    w_index = (tolower(word[i])) - 'a';
                else
                    w_index = word[i] - 'a';
            }
    
            else if (word[i] == '\'')
            {
                w_index = 26;
            }
            if(current->children[w_index] == NULL)
            {
                // Line 54 used to be here overwriting booleans.
                return false;
            }
            else
                current = current->children[w_index];
        }
    
        if(current->is_word == true)
            return true;
        else
            return false;
    
        return true;
    }

**UPDATE**

I looked at your unload function and it seems that things are out of control in the loop. For instance, you go to the next node and you increment your counter:

    cursor = cursor->children[i];
    continue;

That will be like saying:

We have a word that starts with "a".
Good, then check for words that start with "ab".

We have a word that starts with "ab".
Good, then check for words that start with "abc".


We have a word that starts with "abc".
Good, then check for words that start with "abcd".

... And so on.

And when `cursor->children[i]` is indeed `NULL`, `temp` gets freed. At that point `temp` is just the previous node.

This will execute `ALPHABETS` times (27). And with the large dictionary the process will look like the below. I am going to display with letters what will be happening in the code with the nodes:

    a
    ab
    abc
    abcd false
    
    free this node a->b->(c)
    
    abcde false
    
    free this node a->b->(c)
    
    abcdef false
    
    free this node a->b->(c)
    
    abcdefg false
    
    free this node a->b->(c)
    
    abcdefgh false
    
    free this node a->b->(c)

And so on until you get to:

    abcdefghijklmnopqrstuvwxyz' false

    free this node a->b->(c)

free this node a->b->(c)

**SUGGESTION #2**

So, since I don't really know how to unload a trie with an iterative approach, I will show you a recursive approach that I copied and pasted from someone in CS50 Stack Exchange more than a year ago:

    void FreeNode(node* ptr);
    
    bool unload(void)
    {
        // TODO
        FreeNode(root);
        return true;
    }
    
    void FreeNode(node* ptr)
    {
        if (ptr != NULL)
        {   
            for(int i = 0; i < ALPHABETS; i++)
            {   
                FreeNode(ptr->children[i]);
            }   
            free(ptr);
        }   
    }

If you need an explanation on how it works let me know. I am very fond of this function. I think is simple and tenacious.

Depending on how you load your dictionary you might still get errors with valgrind. However, these errors refer to dangerous practices. It will still say that no leaks are possible.