0

I'm not having much luck troubleshooting my speller code. It returns the correct misspelled words and words in text, but words in dictionary returns as 0. I ran valgrind and it said there is a leak in my load (at the line start->child[i] = malloc(sizeof(node));. So I assume the problem is there or is that a separate issue??

// Implements a dictionary's functionality

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

#include "dictionary.h"

typedef struct node

{
    bool is_word;
    struct node *child[27];
}
node;
node *root;

int get_i(const char c)
{
   if (c == '\'')
{
    return 26;
}
else
{
    return tolower(c) % 'a';
}
}

// set counter to zero
int counter = 0;

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

// create memory for root pointer

root = malloc(sizeof(node));

// Open dictionary file
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
    fprintf(stderr, "Could not open. \n"); // Print error if file cannot be 
opened
    return 2;
}

// set new node to root to start process
node *start = root;

for (int x = fgetc(dict); x != EOF; x = fgetc(dict))
{

    if (x == '\n') // if not NULL
    {
        start->is_word = true;
        counter++;
        start = root; // traverse over the trie again from the beginning
    }

    else // if NULL
    {
        int i = get_i(x);

        if (start->child[i] == NULL)
        {
            start->child[i] = malloc(sizeof(node));
        }

        // move to nxt node
        start = start->child[i];

    }
}
free(start);
fclose(dict);
return true;

}

// Returns true if word is in dictionary else false
bool check(const char *word)
{
node *start = root;

// iterate over each letter to build a word; then check if it is a word
for (int i = 0; word[i] != '\0'; i++)
{
    int ind = get_i(word[i]);

    if (start->child[ind] == NULL) // go to the next letter in word
    {
        return false; // if the sequence of letters isnt in the dict it is "misspelled"
    }

    start = start->child[ind]; // if it is !NULL go to next letter
}
return start->is_word;
}

// intialize the word counter to 0
int wordCount = 0;

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
// Using WordCount return the size of the # of words in dict.
return wordCount;

}

// free the children
bool freedom(node *pt)
{
// go through all th children of the corn
for (int z = 0; z < 27; z++)
{
    if (pt->child[z] != NULL)
    {
        freedom(pt->child[z]);
    }
}

free(pt);
return true;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
free(root);
return true;
}
4
  • There are a couple of really important pieces of code that you need to add to the question - the declaration and initialization of counter and the complete size() function. Can I assume that you declared counter as a global?
    – Cliff B
    Nov 26 '18 at 6:44
  • 1
    As for the memory leak, that's most likely a separate issue. Also, valgrind is telling you where the leaked memory was originally allocated, not necessarily where the problem lies.
    – Cliff B
    Nov 26 '18 at 6:45
  • @CliffB I've updated my code to include the initialization and other functions. Also, I moved counter to be global, but I'm still getting the same outcome with my dictionary not returning anything.
    – Beyn18
    Nov 26 '18 at 18:10
  • If you still have questions about the memory leak, please post it as a new question with the latest version of the code. Remember to accept an answer to this question too. ;-)
    – Cliff B
    Nov 26 '18 at 21:10
1

Inside load, you write

    int counter = 0;

This creates a new local variable counter, which no longer exists after leaving load. Move that line out of your function, so the variable is global, accessible from all functions. And be sure to not "shadow" it in any of your functions. Shadowing means declaration of a variable of the same name in an inner scope (a new scope is created most times by curly braces). When the compiler finds a variable name, it searches the current scope, the scope around that one, until it finds a variable of that name. So if you declare a local variable of the same name as a global one, you would not be able to access the global variable by name.

Also, valgrind should complain about use of uninitialised memory. malloc does the allocation, but does not guarantee the allocated memory to have any specific value (it could be anything that was at that memory location previously). You would have to set the memory to the values you want. Using calloc instead of malloc would overwrite allocated bytes with zeroes, which is NULL for pointers and false for booleans, might work for you.

You must log in to answer this question.

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