0
#include <stdbool.h>
#include <cs50.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <stdlib.h>

#include "dictionary.h"

const int HASHTABLE_SIZE = 65536;

typedef struct node
{
    char word[LENGTH + 2];
    struct node *next;
}
node;
// hashtable
node* hashtable[HASHTABLE_SIZE];

int hash_table(const char* hashtabl)
{
    unsigned int hash = 0;
    for (int i=0, n=strlen(hashtabl); i<n; i++)
        hash = (hash << 2) ^ hashtabl[i];
    return hash % HASHTABLE_SIZE;
}

// Returns true if word is in dictionary else false
bool check(const char *word)
{
   // make lower case words
    char lcword[LENGTH+2];
    // convert to lowercase, as we need this to lookup. TODO: change from length to length of word
    for (int i = 0; i < LENGTH+2; i++)
    {
        lcword[i] = tolower(word[i]);
    }
    // set cursor
    node *cursor = hashtable[hash_table(lcword)];

    while (cursor != NULL)
    {
        // check node's word, ignoring case
        if (strcasecmp(word, cursor->word) == 0)
        {
            return true;
        }
        cursor = cursor->next;
    }
    return false;
}


// Load dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
     char word[LENGTH+2];

    // open my dictionnary file (read)
    FILE *dicptr = fopen(dictionary, "r");

    while (fscanf(dicptr, "%s", word) != EOF)
    {
        // make new word.
        node *new_node = malloc(sizeof(node));

        // check for any error
        if (new_node == NULL)
        {
            unload();
            return false;
        }
        else
        {
            // copy word in to node
            strcpy(new_node->word, word);

            int n = hash_table(new_node->word);

            // insert in to my list
            new_node->next = hashtable[n];
            hashtable[n] = new_node;
       }
    }
    // close dicptr
    fclose(dicptr);
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    // dictionary size counter
    int counter = 0;
    // iterate through hashtable
    for (int i = 0; i < HASHTABLE_SIZE; i++)
    {
        // set pointer to head of list
        node *cursor = hashtable[i];
        // traverse list
        while (cursor != NULL)
        {
            counter++;
            cursor = cursor->next;
        }
    }
    return counter;
}

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

        while (cursor != NULL)
        {
            node* tmp = cursor;
            cursor = cursor->next;

            free(tmp);
        }
        free(cursor);
    }

    return true;
}

~/pset5/speller/ $ valgrind ./speller ==23098== Memcheck, a memory error detector ==23098== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==23098== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==23098== Command: ./speller ==23098== Usage: ./speller [DICTIONARY] text ==23098== ==23098== HEAP SUMMARY: ==23098== in use at exit: 0 bytes in 0 blocks ==23098== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated ==23098== ==23098== All heap blocks were freed -- no leaks are possible ==23098== ==23098== For counts of detected and suppressed errors, rerun with: -v ==23098== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

**:) dictionary.c, dictionary.h, and Makefile exist
:) speller compiles
:) handles most basic words properly
:) handles min length (1-char) words
:) handles max length (45-char) words
:) handles words with apostrophes properly
:) spell-checking is case-insensitive
:) handles substrings properly
:( program is free of memory errors
    valgrind tests failed; rerun with --log for more information.**
2
  • 1
    Look at what else valgrind is telling you: Usage: ./speller [DICTIONARY] text. Program needs to be run with a text file argument to get results analagous to check50. Apr 24, 2020 at 15:06
  • says that my error is in line 40 - lcword[i] = tolower(word[i]); Apr 28, 2020 at 9:51

1 Answer 1

1

A problem is here for (int i = 0; i < LENGTH+2; i++). The intent of the loop is to iterate over word. If the word is cat it "owns" 4 bytes of memory. But the loop is executing LENGTH + 2 times.

1
  • ahhh. how silly of me, completely overlooked that.... thank you so much Apr 28, 2020 at 11:06

You must log in to answer this question.

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