0

i don't know or understand through val grind where and what i'm doing wrong. Except for memory errors my code outputs as correct in check50.

my code

// Implements a dictionary's functionality

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>


#include "dictionary.h"

// Represents number of buckets in a hash table
#define N 26
int quantity = 0;


// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

// Represents a hash table
node *hashtable[N];

// Hashes word to a number between 0 and 25, inclusive, based on its first letter
unsigned int hash(const char *word)
{
    return tolower(word[0]) - 'a';
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // Initialize hash table
    for (int i = 0; i < N; i++)
    {
        hashtable[i] = NULL;
    }


    // Open dictionary
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        unload();
        return false;
    }

    // Buffer for a word
    char word[LENGTH + 1];

    // Insert words into hash table
    while (fscanf(file, "%s", word) != EOF)
    {
        int position = hash(word);
        node *a_node = malloc(sizeof(node));
        if (hashtable[position] == NULL)
        {
            hashtable[position] = a_node;
            strcpy(a_node->word, word);
            a_node->next = NULL;
        }
        else
        {
            strcpy(a_node->word, word);
            a_node->next = hashtable[position];
            hashtable[position] = a_node;
        }
        quantity++;
    }

    // Close dictionary
    fclose(file);

    // Indicate success
    return true;
}

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

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    int position = hash(word);
    node *temp = hashtable[position];
    while (temp != NULL)
    {
        if (strcasecmp(temp->word, word) == 0)
        {
            return true;
            free(temp);
        }
        else
        {
            temp = temp->next;
        }
    }

    return false;
    free(temp);
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    node *temp = malloc(sizeof(node));
    for (int i = 0; i < N ; i++)
    {
        temp = hashtable[i];
        while (temp != NULL)
        {
            node *temp1 = temp;
            temp = temp->next;
            free(temp1);
        }
        free(temp);
    }
    return true;
}

1 Answer 1

1

free(temp); in check is wrong, in both instances. But luckily it is dead code, never executed, because you return earlier.

In unload, you should not malloc, this memory is lost on re-assigning to the variable.

Also, the free(temp); is wrong again, but again has no consequences, as it would be a free(NULL); (remember when you abort the while loop just above it). You can remove that and just keep the free(temp1);. BTW, your variable names have room for improvement.

2
  • thanks a ton! made some changes and it worked! but can you please tell me what happens to the temp i assigned in check isn't the memory still allocated and has to be freed. Jul 29, 2019 at 15:46
  • temp is a pointer, stored on stack, handled automatically. It is pointing to a node still part of a linked list, still in use. If you freed that node now, next time you walked the linked list, you would access the now declared free memory, which valgrind should complain about. malloc and free should be somewhat symmetric. If your function is meant to be idempotent (same result if called twice), you should allocate and free the same memory within, and not change any global variables. And here, that would be zero alloc/free.
    – Blauelf
    Jul 29, 2019 at 16:48

You must log in to answer this question.

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