1

I finished coding the load and check functions, but when I run the program, all the words in the selected text file, like the Austin Powers one, are coming out as misspelled. I am not sure if there is something wrong with my load function or check function. Can someone help me? Here is my code:

/**
 * dictionary.c
 *
 * Computer Science 50
 * Problem Set 5
 *
 * Implements a dictionary's functionality.
 */

#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <ctype.h>
#include <stdio.h>

#include "dictionary.h"

typedef struct node
{
    bool is_word;
    struct node* children[27];
}
node;

node* root; //initializes main node

int count = 0; //initializes int that counts how many words are loaded

/**
 * Loads dictionary into memory.  Returns true if successful else false.
 */
bool load(const char* dictionary)
{
    FILE* file = fopen(dictionary, "r"); //opens dictionary for reading

    root = malloc(sizeof(node));
    node* currNode = malloc(sizeof(node*)); //initializes node that will traverse through trie

    for(int i = 0; i<27; i++)
        root->children[i] = NULL; //sets children of main node to NULL

    char cursor; //initializes char that will temporarily store character read from dictionary

    currNode = root; //sets traversing node to main node


    while(fread(&cursor, sizeof(cursor), 1, file) == 1)
    {
        if(isalpha(cursor) == 1 || cursor == 44) //checks if cursor is either a letter or an apostrophe
        {
            int hash; //determines which place in children will point to cursor

            if(isalpha(cursor) == 1) //letters fill up places 0 through 25
                hash = cursor - 97;

            else
                hash = 26; //apostrophes fill up place 26

            if(currNode->children[hash] == NULL) //checks if indicated place of children is NULL
            {
                node* newNode = malloc(sizeof(node*)); //malloc new node
                currNode->children[hash] = newNode; //stated place of children points to new node
                currNode = currNode->children[hash]; //current node equals new node

                for(int i = 0; i<27; i++)
                    currNode->children[i] = NULL; //sets children of new node to NULL
            }

            else 
                currNode = currNode->children[hash]; //if indicated place of children is not NULL, current node moves to indictaed place of children node

            char peek = fgetc(file); //looks at the next character in file

            if(peek == 10) //checks if the next character is not a letter nor an apostrophe
            {
                currNode->is_word = true; //declares that end of word is reached
                count++; //counts number of words loaded
                ungetc(peek, file); //returns the character which peek got back to the buffer
                currNode = root; //traversing node equals root
            }

        }

    }

    fclose(file); //closes file
    return true; //hopefully is successful 


}

/**
 * Returns true if word is in dictionary else false.
 */
bool check(const char* word)
{
    int length = sizeof(word); //gets size of word

    node* trav = malloc(sizeof(node*)); //establishes traversing node
    trav = root; //sets traversing node to root

    for(int i = 0; i<length; i++) //goes through each letter of word
    {
        int place; //establishes int that represents place in the children array of root

        if(isupper(word[i]) == 1) //converts uppercase letters to lowercase form
            tolower(word[i]);

        if(word[i] == 44) //if character is an apostrophe, place will be 26
            place = 26; 

        else //if character is a letter, place will be any number 0-25 
            place = word[i] - 97; 

        if(trav->children[place] == NULL) //if the place in children is pointing to NULL, return false
            return false; 

        else
            trav = trav->children[place]; //if the place in chiildren if pointing to something, go to the next place

        if(i == length-1)
        {
            if(trav->is_word == false) //on the last letter of word, check if the corresponding place in children has its is_word set to true
                return false; 
        }

    }

    return true;
}


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

    return count;
}

/**
 * Unloads dictionary from memory.  Returns true if successful else false.
 */
bool unload(void)
{


}
1

The main problem here is that none of the code inside the if code block within the while loop is executing for letters. Look at the following:

if(isalpha(cursor) == 1 || cursor == 44)

This is a fairly common problem, which I blame on poor documentation of the isalpha() function. The problem is that this code assumes that if the char is a letter, then isalpha(cursor) will return 1. In fact, it will return 1024. In some documentation, it states that a number will be returned, other docs have other descriptions. Some even have this as a void return and then describe a non-void return.

The best way to deal with this is to treat it as if isalpha() returns true or false and let the system deal with interpreting the return value. Almost all systems and architectures will treat 0 as false and a non-zero (neg or pos) as true. So, the easy solution would be to do this:

if(  isalpha(cursor) || cursor == 44  )

This will evaluate the isalpha() call to true or false and it will be done with it, no matter what the actual return value will be. (BTW, that 1024 that is returned can be different on other architectures and systems. That's why treating it as a bool is more reliable.)

This will get you going, but there are other issues. I wouldn't want to deprive you of the fun of debugging them. ;-) If you're still blocked, the new problems would be a new question.

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

3
  • Thanks so much! I was able to debug both my functions, and they now work fine!
    – Saachi
    Aug 3 '16 at 2:55
  • 1
    I still learn, almost every day, reading your answers. Didn't know isalpha() returned 1024. One more reason to not equal the return of a "bool" function with a number (even with true or false using stdbool.h). Thanks! :P
    – ChrisG
    Aug 3 '16 at 5:46
  • I'm blushing! All kidding aside, that's why I test a lot of stuff when it doesn't look quite right. In this case, or any function with a suspicious return, I'll do something like this: printf(" isalpha return value: %i \n", isalpha('a') ); and see what it does. I've learned a lot by doing this and by debugging problem code here. If anyone wanted to follow suit, they could always go back to old questions and debug them on their own before looking at the answers. ;-)
    – Cliff B
    Aug 3 '16 at 6:16

You must log in to answer this question.

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