0

Here is my code:

// Implements a dictionary's functionality

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

#include "dictionary.h"

// max size of hashtable is 2^16
#define HASHTABLESIZE 65536

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
} node;

// init hashtable
node *hashtable[HASHTABLESIZE];

// init global count for no. of words in dictionary
int wordCount = 0;

// init global bool to check if dict has been loaded
bool dictLoaded = false;

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    int wordLen = strlen(word);
    char tmpWord[wordLen + 1];

    // convert word to all lowercase
    for (int i = 0; i < wordLen; i++)
    {
        tmpWord[i] = tolower(word[i]);
    }

    // adds missing null terminator
    tmpWord[wordLen] = '\0';

    // init index of tmp word in hashlist
    int hashIndex = hash(tmpWord);

    // sets "next" cursor to point to same adress as hash index
    node *cursor = hashtable[hashIndex];

    // if the word is in the dictionary, it should be found in the hashtable
    while (cursor != NULL)
    {
        // string comparison - return true if strcasecmp returns 0
        if (strcasecmp(cursor->word, tmpWord) != 0)
        {
            // if word isn't found yet, advance to next node
            cursor = cursor->next;
        }
        else
        {
            // this means the strcmp returned 0, so the word has been found.
            return true;
        }
    }

    // if it gets to here, that means the word isn't in the hashtable therefore is not in the dict.
    return false;
}

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

    int len = strlen(word);
    for (int i = 0; i < len; i++)
    {
        hash = (hash << 2) ^ word[i];
    }
    return hash % HASHTABLESIZE;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // open selected dictionary file in "read" mode
    FILE *dictionaryFile = fopen(dictionary, "r");

    // safeguard - if unable to read, return false
    if (dictionaryFile == NULL)
    {
        return false;
    }

    // populates hash table with nodes that contain each word in the dict.
    char word[LENGTH + 1];

    // repeat until end of dictionary file (EOF)
    while (fscanf(dictionaryFile, "%s", word) != EOF)
    {
        // allocate mem for each new node
        node *n = malloc(sizeof(node));

        // if malloc is all good, continue, else return false
        if (n == NULL)
        {
            // preventing mem leak - unload dict from memory
            unload();
            return false;
        }

        // since malloc is good now, copy word into node
        strcpy(n->word, word);

        // calculate index of word so we can put the node into the hashtable
        int hashIndex = hash(n->word);

        // init node head to point to hashtable index
        node *head = hashtable[hashIndex];

        // insert node
        if (head == NULL)
        {
            hashtable[hashIndex] = n;
            wordCount++;
        }
        else
        {
            n->next = hashtable[hashIndex];
            hashtable[hashIndex] = n;
            wordCount++;
        }
    }

    // cleanup - close files and return true
    fclose(dictionaryFile);
    dictLoaded = true;
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    if (dictLoaded == true)
    {
        return wordCount;
    }

    else
    {
        return 0;
    }
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    node *head = NULL;
    node *point = head;

    // free linked list
    while (point != NULL)
    {
        node *tmp = point;
        point = point->next;
        free(tmp);
    }
    return true;
}

and this is the output from valgrind:

==1987== Conditional jump or move depends on uninitialised value(s)
==1987==    at 0x401A2C: check (dictionary.c:53)
==1987==    by 0x4015DB: main (speller.c:112)
==1987== 

Line 53 and onwards within the check function of dictionary.c is the following:

   // if the word is in the dictionary, it should be found in the hashtable
    while (cursor != NULL)
    {
        // string comparison - return true if strcasecmp returns 0
        if (strcasecmp(cursor->word, tmpWord) != 0)
        {
            // if word isn't found yet, advance to next node
            cursor = cursor->next;
        }
        else
        {
            // this means the strcmp returned 0, so the word has been found.
            return true;
        }
    }

    // if it gets to here, that means the word isn't in the hashtable therefore is not in the dict.
    return false;
}

Check50 and the program all validate and work correctly, however the valgrind test fails due to this. How can I fix it?

You must log in to answer this question.

Browse other questions tagged .