0

I fixed a few problems and everything looks like it is loading, checking and unloading correctly. GDB isn't picking up any errors and I can't figure out where the error is.

:) dictionary.c, dictionary.h, Makefile exist
:) speller compiles
:( handles most basic words properly \ expected output, not standard error of "/opt/sandbox50/bin/run.sh: line 31: 252..."
:( handles min length (1-char) words \ expected output, not standard error of "/opt/sandbox50/bin/run.sh: line 31: 252..."
:( handles max length (45-char) words \ expected output, not standard error of "/opt/sandbox50/bin/run.sh: line 31: 251..."
:( spell-checking is case-insensitive \ expected output, not standard error of "/opt/sandbox50/bin/run.sh: line 31: 252..."
:( handles possessives properly \ expected output, not standard error of "/opt/sandbox50/bin/run.sh: line 31: 253..."
:( handles substrings properly \ expected output, not standard error of "/opt/sandbox50/bin/run.sh: line 31: 252..."
https://sandbox.cs50.net/checks/1d95e07da2564302ba81da4982ab26f9

WORDS MISSPELLED: 644
WORDS IN DICTIONARY: 143091
WORDS IN TEXT: 19190
TIME IN load: 0.02
TIME IN check: 0.52
TIME IN size: 0.00
TIME IN unload: 0.00
TIME IN TOTAL: 0.55

#include <stdbool.h>
#include <stdio.h>
#include <cs50.h>
#include "dictionary.h"
#include <ctype.h>
#include <string.h>

//Prototypes
int hash_table(char *key);

//GLOBALS

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

node *node_array[27] = {NULL};
unsigned int SIZE;

/**
 * Returns true if word is in dictionary else false.
 */
bool check(const char* word)
{
    //Copy const char word into temp_word for manipulation and to pass to hash key function
    char temp_word[sizeof(word + 1)];
    strcpy(temp_word, word);

    for(int i = 0, n = strlen(temp_word) + 1; i < n; i++)  // all caps are converted to lowercase
    {
        temp_word[i] = tolower(temp_word[i]);
    }

    int key = hash_table(temp_word);           
    node *crawler;     //Set crawler to head to traverse list

    crawler = node_array[key];

    while(crawler)
    {
        int compare = strcmp(temp_word, crawler->word);
        if(compare == 0)
        {
            return true;
        }
        crawler = crawler->next;
    }



    printf("mispelled - %s\n", temp_word);
    return false;
}

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

    if(file == NULL)
    {
        printf("File does not exist or is corrupted\n");
        return false;
    }
    char temp_word[LENGTH + 1];
    SIZE = 0;

    //Need to iterate through file until the end holding each string in a variable to be insterted into node_n->word
    while(fscanf(file, "%s", temp_word) !=EOF)
    {
        //Use temp_word as argument in hash function
        int key = hash_table(temp_word);

        node *new_node = malloc(sizeof(node));
        strncpy(new_node->word, temp_word, sizeof(temp_word));

        //Use returned hash to input into array of structs if there is space in array
        if(node_array[key] == NULL)
        {
            node_array[key] = malloc(sizeof(node));
            node_array[key] = new_node;
            new_node->next = NULL;
        }
        //If array location is used begin linked list
       else
        {
            new_node->next = node_array[key]->next;
            node_array[key]->next = new_node;
        } 
        SIZE++;  //Count words loaded to be passed to Size function
    }
    printf("%d", SIZE);
            return true;
}

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

/**
 * Unloads dictionary from memory.  Returns true if successful else false.
 */
bool unload(void)
{
    node *crawler;
    node *node_free;
    int counter = 0;
    //Loop through each element in array
    for(int i = 0, n = 26; i < n; i++)
    {
        crawler = node_array[i];     // <-- Set crawler to head
        while(crawler->next != NULL)   // <-- Crawl through linked list freeing nodes until we hit the end.
        {
            node_free = crawler;
            crawler = crawler->next;
           // printf("unload - %s\n", node_free->word);
            free(node_free);
            counter ++;
        }
        counter ++;
    }
    if(counter == SIZE)
        {
        return true;
        }
    return false;
}

  //Create hash function which indexes words to an array of 26 linked lists - alphabet - Key will be 

int hash_table(char key[LENGTH + 1])
{
    int hash = toupper(key[0]) - 'A';
    return hash % 26;
}
1

The problem lies in your declaration of temp_word:

char temp_word[sizeof(word + 1)];

There are a couple of errors here. I'm not sure what effect the + 1 inside of the parentheses will have, but sizeof(word) returns the size of the pointer word, which is 8, not the length of the string word. Instead, it should be using strlen(word) + 1 to get the string length plus 1 for the end of string marker.

Because of this error, anytime a word longer than about 7 or 8 chars is checked, it causes problems because it would overwrite the vars that follow. The longer the word, the worse the damage.

BTW, there's still a nasty little memory leak, as previously discussed. ;-)

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

  • Thanks! I fixed that but it is still failing check50. Would the memory leek cause that to fail? I thought I fixed those! Also does the check50 results actually mean I have a seg fault because no seg faults show in gdb or when running the program? – Ryan McCauley Jul 13 '16 at 21:47

You must log in to answer this question.

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