0

Hi stackexchange I was needing some advice as my speller does work but the only thing it does not do correct it looks like is count the correct words in the dictionary. For some reason I am getting these errors in check50.

:( handles most basic words properly
   \ expected output, but not "\nMISSPELLED WORDS\n\n\nWORDS MISSPELLE..."  
:( handles max length (45-char) words
   \ expected output, but not "\nMISSPELLED WORDS\n\n\nWORDS MISSPELLE..."  
:( spell-checking is case-insensitive
   \ expected output, but not "\nMISSPELLED WORDS\n\n\nWORDS MISSPELLE..."  
:( handles possessives properly
   \ expected output, but not "\nMISSPELLED WORDS\n\nfoo's\n\nWORDS MI..."  

Everything else is a smiley face in check50. here is my code in dictionary.c

/**
 * Implements a dictionary's functionality.
 */

#include <stdbool.h>
#include <stdio.h> // to make file
#include <stdlib.h> // one of the functions is it allows to malloc data
#include <string.h> // allows functions like strcpy
#include <strings.h>
#include "dictionary.h"
#include <ctype.h> // allows functions like to lower

#define HASHSIZE 26

typedef struct node //create to implement nodes and global so all functions can use
{
    char word[LENGTH + 1];
    struct node *next;
}node;

int hash_it(char* word); //prototyped hash function it before the load() function
node* hashtable[HASHSIZE];

/**
 * Returns true if word is in dictionary else false.
 */
bool check(const char *word)
{
    // TODO
    char word2[LENGTH +1];
    strcpy(word2, word);
    int result;

    for(int i = 0, j = strlen(word2); i <j; i++) // need to lowercase the text word because word in the dictionary is also lower
    {
        word2[i] = tolower(word2[i]);
    }
    // this is need because the hash word here needs to match the format(in this case lowercase) of the hash word in the dictionary hashtable as it is how it can access it
    int checkedhash = hash_it(word2);

    node *cursor = hashtable[checkedhash]; // pointer cursor points to whatever hashtable is pointing to and gets its word as it points to that
    while( cursor != NULL)
    {
        result = strcasecmp(word2, cursor->word);// word2 is the text word while curosr->word is the dictionary word in the hashtable
        if(result ==0)
        {
            return true;
        }
        else
        cursor = cursor->next;
    }
    return false;
}

/**
 * Loads dictionary into memory. Returns true if successful else false.
 */
bool load(const char *dictionary)
{
    // TODO use hash table
    FILE *file = fopen(dictionary, "r"); //get the dictionary file so you can get the words to load

    if (file == NULL)
    {
        printf("Could not load %s.\n", dictionary);
        unload();
        return 1;
    }

    char word[LENGTH + 1];

    while(fscanf(file, "%s", word) != EOF) // makes a word from the file into a node until the end of the file
    {

        node *new_node = malloc(sizeof(node));
        if (new_node == NULL)
        {
            unload();
            return false;
        }
        strcpy(new_node->word, word);
        //hash function to put in buckets remember to source!
        int hashval = hash_it(new_node->word);
        // put hashed word into bucket and created linked lists for each word by order of the alphabet

        new_node->next = hashtable[hashval];
        hashtable[hashval] = new_node;
    }
    //implement hash code?

    return true;
}

int hash_it(char* word)// hash function puts words a through z
{
   return *word - 'a';
}

/**
 * Returns number of words in dictionary if loaded else 0 if not yet loaded.
 */
unsigned int size(void)
{
    // TODO
    int count = 0;

    for(int i = 0; i < 26; i++)
    {
        node *cursor = hashtable[i++];
        while(cursor != NULL)
        {

            cursor = cursor ->next;
            count++;
        }
    }
    return count;
}

/**
 * Unloads dictionary from memory. Returns true if successful else false.
 */
bool unload(void)
{
    // TODO
    for(int i = 0; i < 26; i++)
    {
    node *cursor = hashtable[i++];

    while(cursor != NULL)
    {
        node *temp = cursor; // created pointer to free up each node 
        cursor = cursor ->next;
        free(temp);
    }
    }
    return true;
}
1

You're right. All those errors are being generated because the word count is incorrect. It's a good learning exercise that you decided to count the words by traversing the tree to count the words. Unfortunately, the code is skipping about half of the linked lists. Look at the following code:

for(int i = 0; i < 26; i++)
{
    node *cursor = hashtable[i++];
    ...
}

See anything wrong? What is the value of i when the loop starts, then after the creation of cursor, and finally, when the loop comes back up to the for statement to repeat? If you're not sure, try running it through debug.

As a side note, do you think there's an easier way? What if you counted the number of words while creating the tree in the load function?

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

3
  • Oh wow haha I forgot the i is already incrementing by one in the for loop so I don't need the i++ in the for loop correct? And hmm so regarding the other way to count the number of words. So are you saying I can just count the words in the tree in the load function and maybe place a return count at the end of the load function also would work or would I need to transfer it to my size function as in create a global variable for the count? And thank you for you help cliff B! – Roundabout Jun 2 '17 at 23:47
  • Well, you're half right. You can count the words in load, but you can't return the wordcount. Remember, you can only return one value, and according to the spec, it must be a bool indicating success of failure at loading the dictionary. Now, if only there were a way to store a value globally. hmmm...;-) – Cliff B Jun 2 '17 at 23:57
  • Ah same as the hashtable I believe awesome! – Roundabout Jun 3 '17 at 1:10

You must log in to answer this question.

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