Reputation: 13
The program runs a spellcheck on a text paired with a given dictionary(CS50: Pset5 Speller). The dictionary file is in form of a txt file, which is loaded into memory in the form of a hash table.
The check function takes an argument of a word that is read from the text file. the word is hashed and compared to any elements exist in a given individual hash table. If a word exist it returns true, else false.
The Hash is hashing any given word, while Load function is loading words from the dictionary to corresponding hash index of the word in the hash table. Load Function takes a pointer to the dictionary as an argument.
Size function is measuring the size of the dictionary by pointing to existing hash table.
Unload function reiterates over each possible index of the hash table while simultaneously calling for ClearNodes which checks for contents in the linked list that is connected to the hash table.
I've tried resizing the texts and dictionaries to smaller sizes, and also i tried to place my breakpoint before and after individual function is called (since somehow placing the breakpoint after main() loads the dictionary
and Finished checking all the words in a given text
, then in the debugger manually pressing step-over
until main()
is finished, managed to make the program terminated normally). With smaller sizes dictionary and texts i didnt found any resemblance that causes the function to not return a value. Bear in mind the unload function is assume to always return true at this point and it isnt finished.
Help is greatly appreciated.
// Implements a dictionary's functionality
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// TODO: Choose number of buckets in hash table
const unsigned int N = 17576;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
//Create Word Hash Value
int WordHashIndex = hash(word);
node *Temp = table[WordHashIndex];
//Jump to Hash Index
while(Temp != NULL)
{
if(strcasecmp(Temp -> word, word) != 0)
{
Temp = Temp -> next;
}
else
{
return true;
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO: Improve this hash function
if(word[1] == '\0')
{
return (toupper(word[0]) - 65);
}
else if(word[2] == '\0')
{
return ((toupper(word[0]) - 65) + ((((toupper(word[1]) - 65) * 26) > -1) ? ((toupper(word[1]) - 65) * 26) : 0));
}
else
{
return ((toupper(word[0]) - 65) + ((((toupper(word[1]) - 65) * 26) > -1) ? ((toupper(word[1]) - 65) * 26) : 0) + ((((toupper(word[2]) - 65) * 676) > -1) ? ((toupper(word[2]) - 65) * 676) : 0));
}
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
int HashedIndex = 0;
char TempWord[LENGTH + 1];
int CharLengthCounter = 0;
FILE *LoadedDictionary = fopen(dictionary, "r");
if(LoadedDictionary == NULL)
{
return false;
}
while(fscanf(LoadedDictionary, "%s", TempWord) != EOF)
{
HashedIndex = hash(TempWord);
node *TempNode = NULL;
//Jump To HashedIndex
if(table[HashedIndex] != NULL)
{
TempNode = malloc(sizeof(node));
TempNode -> next = table[HashedIndex] -> next;
table[HashedIndex] -> next = TempNode;
strcpy(TempNode -> word, TempWord);
}
else
{
TempNode = malloc(sizeof(node));
table[HashedIndex] = TempNode;
strcpy(table[HashedIndex] -> word, TempWord);
}
}
if(LoadedDictionary != NULL)
{
free(LoadedDictionary);
return true;
}
else
{
return false;
}
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
node *Temp;
int DictSize = 0;
for(int Counter = 0; Counter < N; Counter++)
{
Temp = table[Counter];
if(Temp != NULL)
{
DictSize++;
while(Temp -> next != NULL)
{
Temp = Temp -> next;
DictSize++;
}
}
else
{
continue;
}
}
if(DictSize != 0)
{
return DictSize;
}
else
{
return 0;
}
}
//Check Node Data and Length Inside Each Table
bool ClearNodes(node *CurrentIndex)
{
if(CurrentIndex != NULL)
{
if(CurrentIndex -> next != NULL)
{
if(ClearNodes(CurrentIndex -> next))
{
free(CurrentIndex);
return true;
}
}
else
{
free(CurrentIndex);
return true;
}
}
return false;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
int TableElementsCheck = 0;
for(int Counter = 0; Counter < N; Counter++)
{
ClearNodes(table[Counter]);
}
return true;
}
Upvotes: 1
Views: 268
Reputation: 25261
Your question has at least the following bugs in the function load
:
The following block is wrong:
else
{
TempNode = malloc(sizeof(node));
table[HashedIndex] = TempNode;
strcpy(table[HashedIndex] -> word, TempWord);
}
You are forgetting to set TempNode->next
to NULL
.
Also, the line
free(LoadedDictionary);
is wrong. You should call fclose
instead of free
on a FILE *
returned by the function fopen
.
After fixing these bugs, the output appears correct:
MISSPELLED WORDS
A
is
not
a
This output is correct because those words do not exist in the dictionary that you provided. The words cat
and caterpillar
were not printed as wrong, because they were in the dictionary.
Upvotes: 1