1

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.

9

It's something you overlooked. Your hash function determines the hash value by adding the ASCII values of every letter in the word. The problem is that an upper case letter won't produce the same hash as the same letter in lower case.

Since you don't convert the word being checked to lower case before hashing it, you get the wrong hash number and search the wrong part of the dictionary.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

| improve this answer | |
  • Good an easy fix (that I probably never would have noticed). Checks loads and check seem to be working now. Thanks. – Brandon Terry Aug 18 '16 at 17:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .