I've been working on PSET5 for weeks now on & off and I'm becoming really frustrated. I think I'm lacking some understanding of the malloc/free relationship, I'm not sure. Here's all of my code. Valgrind returns issues at line 70 & 124. Speller combines but check50 has sad faces for almost everything (although it had fewer sad faces a few days ago, and I haven't changed anything since!). I have no idea what to do or where my problems are. I compared my code against some online solutions and could not find anything significantly logically different. I'm finding this extremely challenging and would appreciate any help.
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdint.h>
#include <ctype.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 65536;
// Hash table
node *table[N];
//Dictionary word count
int wordcount = 0;
// Returns true if word is in dictionary else false
bool check(const char *word)
{
//Get hash value of the word
unsigned int h = hash(word);
//Access linked list at that index in the hash table
node *cursor = malloc(sizeof(node));
//Check in case there is not enough memory
if (cursor == NULL)
{
return false;
}
//Initialise cursor to traverse the linked list
cursor = table[h];
//Compare the contents of the linked list with the word
while (cursor != NULL)
{
if (strcasecmp(cursor->word, word) == 0) //If the words match
{
return true;
}
else //If the words don't match
{
cursor = cursor->next;
}
}
//Otherwise, return false
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
//New lowercase word
char *lword = malloc(strlen(word) + 1);
//Copy the word
strcpy(lword, word);
//Make all words lowercase
for (int i = 0; i < strlen(lword); i++)
{
if (isalpha(lword[i]))
{
lword[i] = tolower(lword[i]);
}
}
//Hash function credit: djb2 by Dan Bernstein
unsigned long hash = 5381;
int c;
while ((c = *lword++))
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
free(lword);
return hash % N;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
//Open dictionary file
FILE *file = fopen(dictionary, "r");
//Check if a return value is NULL
if (file == NULL)
{
return false;
}
//Declare new variable
char word[LENGTH + 1];
//Read strings from file one at a time
while (fscanf(file, "%s", word) != EOF)
{
fscanf(file, "%s", word);
//Allocate memory to store a new node
node *n = malloc(sizeof(node));
//Check in case there is not enough memory
if (n == NULL)
{
return false;
}
//Hash word to obtain a hash value
unsigned int index = hash(word);
//If first element of the linked list
if (table[index] == NULL)
{
table[index] = n;
n->next = NULL;
}
//If the linked list is already populated
else
{
n->next = table[index];
table[index] = n;
}
//Copy word into the node
strcpy(n->word, word);
wordcount++;
}
fclose(file);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
return wordcount;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
for (int i = 0; i < N; i++)
{
//Initialise cursor
node *cursor = table[i];
//Until cursor is NULL
while(cursor != NULL)
{
node *tmp = cursor;
cursor = cursor->next;
free(tmp);
}
}
return true;
}