Think I've managed to get everything to work. The program compiles and loads large or small dictionaries and finds misspelled words in various text files.
I diffed the output of my speller with staff's implementation and besides the time differences, I consistently have an extra word in the dictionary. I believe it might be something to do with me using the feof()
function in load()
, but can't be sure. The rest of the output is exactly the same as staff's program.
Check50 is red and frowning all the way though. Not sure what is going on. Please have a look at my code.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "dictionary.h"
// size of the hash table
#define TABLESIZE 27
// size of the dictionary
unsigned int dictSize = 0;
// build the node for the hash table
typedef struct node
{
char word[LENGTH+1];
int hashkey;
struct node* next;
}
node;
// construct the root node array of the hash table
node* hashtable[TABLESIZE];
// simple hash function
int hash(const char* word)
{
return abs(toupper(word[0]) - 'A');
}
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
// convert the word to lowercase before checking the dictionary
char lowercase[LENGTH+1];
for(int i = 0, j = strlen(word) + 1; i < j; i++)
{
lowercase[i] = tolower(word[i]);
}
//walk through the dictionary
int index = hash(lowercase);
for(node *ptr = hashtable[index]; ptr != NULL; ptr = ptr->next)
{
if(strcmp(lowercase, ptr->word) == 0)
{
return true;
}
}
return false;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
for (int i = 0; i < TABLESIZE; i++)
{
hashtable[i] = NULL;
}
//open the dictionary file
FILE* dPtr = fopen(dictionary, "r");
if (dPtr == NULL)
{
printf("Could not open dictionary file.\n");
unload();
return 1;
}
//assign values to the node
while(!feof(dPtr))
{
node* newNode = malloc(sizeof(node));
if (newNode == NULL)
{
exit(1);
}
fscanf(dPtr, "%s", newNode->word);
newNode->hashkey = hash(newNode->word);
newNode->next = hashtable[newNode->hashkey];
hashtable[newNode->hashkey] = newNode;
dictSize++;
if(feof(dPtr))
{
fclose(dPtr);
return true;
}
}
return false;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
return dictSize;
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
for (int i = 0; i < TABLESIZE; i++)
{
node* cursor = hashtable[i];
while(cursor != NULL)
{
node* temp = cursor;
cursor = cursor->next;
free(temp);
}
}
return true;
}
Excuse me for pasting the whole dictionary.c here, but I'm really not sure why it keeps failing check50.