I'm getting my spell checker to load and check. It appears to work (as far as I've tested thus far) except for I can't get it to be case insensitive.
I've tried a couple of approaches, but in both cases, I copied the word from the text file to a new char*, so it could be modified.
In the code below, I attempted to use a loop to recopy the string using tolower to lowercase all words. In a different attempt, I tried to use strcpy to copy the word and then use strcasecmp to compare the word to the dictionary word.
Here's my code:
#include <stdbool.h>
#include "dictionary.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <strings.h>
#include <string.h>
#include <ctype.h>
#define HASHSIZE 100 //higher size = more memory but more buckets and quicker time
//declare global variables
FILE* bufferdictionary;
//struct node to create linked list for each "bucket" - will be used in load and check
typedef struct node
{
char word[LENGTH + 1]; // + 1 for word terminator
struct node* next;
}
node;
//create hashtable of max HASHSIZE and of data type node defined above
node* hashtable[HASHSIZE];
//hash function per cs50 video but stated not to be the best so could improve upon
unsigned int hash(const char* string)
{
int sum = 0;
for(int i = 0; string[i] != '\0'; i++)
{
sum += string[i];
}
return sum % HASHSIZE; //modulo of the sum limits number of keys/buckets to HASHSIZE
}
//word counter
int number_of_words = 0;
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
// TODO
//create node to crawl list
node* crawler = malloc(sizeof(node));
//hash word from text document - 'word' is array name indicated in speller.c
int hashkey = hash(word);
//point crawler to correct bucket of hashtable
crawler = hashtable[hashkey];
//create memory to store a copy of the word in lower case
int lenword = strlen(word);
char* wordcopy = malloc(lenword * sizeof(char));
//strcpy(wordcopy,word);
for(int i = 0; i < lenword; i++)
{
wordcopy[i] = tolower(word[i]);
}
//loop until reaching the end of the list
while(crawler != NULL)
{
//use strcasecmp to see if word from dictionary loaded at the current node equals word (string array) from text file (per speller.c)
//note strcmp equals 0 if it is a match
if(strcmp(crawler->word, wordcopy) == 0)
{
return true;
}
//if strings not equal, move crawler to the next node and then repeat loop (check for word) at that node
crawler = crawler->next;
}
return false; //crawler is null and never found word in singly linked list at the location of the bucket the word should be at
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
//defines string for dictionary word
char dictword[LENGTH + 1];
//open dictionary or return false if can't
bufferdictionary = fopen(dictionary, "r"); //note: dictionary is a char for the command line dictionary declared in speller.c
if (bufferdictionary == NULL)
return false;
//use fscanf to read words and store in buffer - for array have to know number of words, hash table or trie this will happen dynamically (no for loop?)
while(fscanf(bufferdictionary, "%s", dictword) != EOF)
{
//get the bucket/hashkey for the word scanner from the dictionary
int hashkey = hash(dictword);
//create a place in memory for the new node
node* new_node = malloc(sizeof(node));
//check if no memory for new node
if (new_node == NULL)
{
printf("No memory able to be allocated to new_node. Program ending.");
return false;
}
//if there is not a node add haskey, add it and make sure it points to NULL
if(hashtable[hashkey] == NULL)
{
hashtable[hashkey] = new_node;
new_node -> next = NULL;
}
//else insert new node
else
{
//point new node to the current node entry at the beginning of that entry (so now hashkey and new node are point to the entry)
new_node->next = hashtable[hashkey];
//now have hashkey point to newnode (rather than the one it was already pointing to/new_node is now pointint to)
hashtable[hashkey] = new_node;
}
//new_node->word = dictword;
// comment above doesn't work can't assign an array, only copy it. This is because array is a pointer not a value?
strcpy(new_node->word, dictword);
number_of_words++;
}
//fclose(bufferdictionary);
return true;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
// TODO - load already returns 0 if not yet loaded. when tried checking for this, it said load will always be true (because has to make it to this point in the program?)
return number_of_words;
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
// TODO - reporting true or false if successful is taken care of in speller.c
//will need to crawl each hash bucket and crawl to free each node
{
return true;
}
//return false;
}
Been wrapping my head around this for a while and tried to search for similar problems but couldn't find help. Thanks in advance.