0

When I run check on my code, it shows that my program marks all the words in the given text as misspelled. I've made sure to pass a lower case copy of the words into my hash function before they are checked, but I'm stumped as to the reason why they are still being marked as misspelled. Here's part of my dictionary.c code below

unsigned fnv_hash(void *key, int len)
{
unsigned char *p = key;
unsigned h = 2166136261;
int i;

for (i = 0; i < len; i++)
{
    h = (h * 16777619) ^ p[i];
}

return h;
}

typedef struct node
{
    char value[LENGTH + 1];
    struct node* next;
}
node;

node* hashtable[HASHTABLE_SIZE];

int word_count = 0; 
bool loaded;

/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
//Create a new pointer that points to a copy of word so that it may be used   in the hash function
char* wordindex = malloc(LENGTH+1);
char  wordcopy = *word;
*wordindex = wordcopy;

//Change word to all lower case letters
for(int i = 0; i < strlen(word); i++)
{
    if(wordindex[i] == '\'')
    {
        wordindex[i] = wordindex[i];
    }
    else if(isupper(wordindex[i]))
    {
        wordindex[i] = wordindex[i] + 32;
    }
    else if(islower(wordindex[i]))
    {
        wordindex[i] = wordindex[i];
    }

}

//pass word through hash function and get the index
int len  = strlen(wordindex);
unsigned int fnv_output = fnv_hash(wordindex, len);

//Fit within hashtable bucket range
int index = fnv_output % HASHTABLE_SIZE;

node* cursor = hashtable[index];

while(cursor != NULL)
{
    int a = strcmp(cursor->value, word);

    if(a == 0)
    {
        return true;
    }

    else if(a != 0)
    {
        cursor = cursor->next;
    }
}

free(cursor);
return false;
   }
  /**
  * Loads dictionary into memory.  Returns true if successful else false.
  */
  bool load(const char* dictionary)
{
 //open the dictionary
FILE *fp;
fp =  fopen(dictionary, "r");

while(fp != NULL)
{
    node* new_node = malloc(sizeof(node));

    if(new_node != NULL && fscanf(fp, "%s", new_node->value) != EOF)
    {
            //this is a new word, update counter
            word_count++;

            //FNV Hash word//
            int len  = strlen(new_node->value);
            unsigned int fnv_output = fnv_hash(new_node->value, len);

            //Fit to range of hashtable//
            int index = fnv_output % HASHTABLE_SIZE;

            //Insert node at the end of the linked list at proper index//
            new_node->next = hashtable[index];
            hashtable[index] = new_node;
    }

    else if (fscanf(fp, "%s", new_node->value) == EOF)
    {
        free(new_node);
        loaded = true;
        return true;
    }
}

loaded = false;
return false;
 }

1 Answer 1

0

Your check function is returning the same hash value for every word because it doesn't hash the actual word, it's hashing an address. You can't copy a string with the = operator. Instead, you need to use something like strcpy().

AS a side note, you should look at some of the efficiencies in your code.

In check, you go from word to wordcopy to wordindex. You could probably eliminate wordcopy from the process.

Whenever you call your hash function, you always follow it with a modulo operation to make sure the result is in range. Instead, you could do that inside the hash function once, making sure it is always done and eliminate both duplication of code and the chance that it might be left out on one of the calls to the hash function.

In your check, you have a for loop to shift everything to lower case. Instead of 12 lines of code, you could do it in one line: wordindex[i] = tolower(wordindex[i]) ;. tolower changes uppercase to lowercase, but does nothing to any other characters.

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

You must log in to answer this question.

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