A couple questions here.
I'm trying to figure out Week 5 Pset5 Speller. Here is my code:
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.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 = 1000;
// Hash table
node *table[N];
// Dictionary size
int dictionary_size = 0;
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO #4!
// make lowercase copy of word
char copy[strlen(word) + 1];
for (int i = 0; i < strlen(word); i++)
{
copy[i] = tolower(word[i]);
}
// get hash value
int h = hash(copy);
// use hash value to see if word is in bucket
if (table[h] != NULL)
{
node *temp = table[h];
while (temp != NULL)
{
if (strcmp(temp->word, copy) == 0)
{
return true;
}
temp = temp->next;
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO #2
// source: https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/cf9189q/
// I used this source because I had trouble understanding different variations - this one explained everything well.
// I modified it slightly to fit my needs
unsigned int hash = 0;
for (int i = 0; i < strlen(word); i++)
{
hash = (hash << 2) ^ word[i];
}
return hash % N;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO #1!
// open dictionary file
FILE *file = fopen(dictionary, "r");
if (file == NULL)
{
return false;
}
// read strings from file one at a time
char word[LENGTH + 1];
while (fscanf(file, "%s", word) != EOF)
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
// place word into node
strcpy(n->word, word);
// use hash function to take string and return an index
int h = hash(word);
// make the current node point to the bucket we want
n->next = table[h];
// make the bucket start now with the current node
table[h] = n;
//count number of words loaded
dictionary_size++;
}
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO #3!
return dictionary_size;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO #5!
for (int i = 0; i < N; i++)
{
while (table[i] != NULL)
{
node *temp = table[i]->next;
free(table[i]);
table[i] = temp;
}
}
return true;
}
Question Part 1:
When I run Check50, the only error that shows is the last one:
:) dictionary.c exists
:) 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; see log for more information.
When I check Help50 Valgrind, it says:
==658== Conditional jump or move depends on uninitialised value(s)
Looks like you're trying to use a variable that might not have a
value? Take a closer look at line 70 of dictionary.c.
Valgrind then asks me to look at line 70, but I can't figure out what it's upset with. (Line 70 is the "for" line in the hash function). I've also tried moving the "strlen(word)" portion to be its own variable in case that's what it was upset about, and it still didn't agree with what I had done:
unsigned int hash(const char *word)
{
// TODO #2
// source: https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/cf9189q/
// I used this source because I had trouble understanding different variations - this one explained everything well.
// I modified it slightly to fit my needs
unsigned int hash = 0;
int j = strlen(word);
for (int i = 0; i < j; i++)
{
hash = (hash << 2) ^ word[i];
}
return hash % N;
}
Can someone explain what valgrind is asking me to do?
Question Part 2: this part has been fixed :) see comments if you are curious about what was fixed in this portion of my question
Although Check50 is mostly happy with my code, I have run it multiple times and found my results do not match the staff results. For example, when I run ./speller texts/lalaland.txt
, I get 2476 misspelled words while the staff got 955 misspelled words. I have the same number of words in the dictionary, but something in my code is not working the way it should. Can anyone help me identify where my problem is?
Much appreciated!!