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?