I'm stuck on Pset5, Speller. My code all compiles correctly, and when run on the Lala Land example, provides the same output as the staff solution (albeit mine runs more slowly). But, check50 still shows mainly wrong:
:) dictionary.c, dictionary.h, and Makefile exist
:) speller compiles
:( handles most basic words properly
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles min length (1-char) words
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles max length (45-char) words
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles words with apostrophes properly
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( spell-checking is case-insensitive
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:( handles substrings properly
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:| program is free of memory errors
can't check until a frown turns upside down
I've looked at questions with a similar problem and have tried running the code with a one word dictionary as both the dictionary and the text. I've also tried a text of 26 lines, with one letter on each line (a->z). In each case, the output line 'Words in Text' shows one fewer word than the actual number of words in the text. Could this be the problem? I don't see why this could be the error, though, because nothing in the dictionary.c file affects this 'words in text' count..?
For example, this is the output when I run ./speller texts/Untitled1, where Untitled1 is 26 lines with a->z, one letter per line:
WORDS MISSPELLED: 23
WORDS IN DICTIONARY: 143091
WORDS IN TEXT: 25
TIME IN load: 0.03
TIME IN check: 0.01
TIME IN size: 0.00
TIME IN unload: 0.00
TIME IN TOTAL: 0.04
Here is my code:
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <stdlib.h>
#include "dictionary.h"
void copy_string(char *target, char *source);
int word_count = 0;
// 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 = 26;
// Hash table
node *table[N];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
int key = hash(word);
node *cursor = table[key];
while (cursor != NULL)
{
if (strcasecmp(cursor->word, word) == 0)
{
return true;
}
else
{
cursor = cursor->next;
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
unsigned int hash_value = 0;
for (int i = 0; word[i] != '\0'; i++)
{
hash_value = tolower(word[i]);
}
return hash_value % N;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
//fopen dictionary - > creates file
FILE *dict = fopen (dictionary, "r");
if (dict == NULL)
{
//check if loaded correctly using NULL. If null return false.
printf("Could not open dictionary.\n");
return false;
}
//initialise hash table, with it initially blank
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
//create character array of length LENGTH for individual words to go in
char word[LENGTH + 1];
//repeat below for each of the words in the dictionary
while (fscanf(dict, "%s\n", word) != EOF)
{
//create new node into which to put the new word and add 1 to the word count
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
return false;
}
else
{
//copies the word into the new node
strcpy(new_node->word, word);
//figures out the hash for the word
int h = hash(word);
//if nothing in the hash table at the hash value index
//puts the new node at that index, with the next pointer as NULL
//(there are no other vaulues in that table yet)
if(table[h] == NULL)
{
new_node->next = NULL;
table[h] = new_node;
}
//if already something in the hashtable, we point the new node to
//the first item in the hashtable at that index
//then set the first item to be the new node.
else
{
new_node->next = table[h];
table[h] = new_node;
}
word_count ++;
}
}
fclose(dict);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
//gives the number of words in the dictionary
if (word_count > 0)
{
return word_count;
}
else
{
printf("Empty dict, or no dict loaded\n");
return 0;
}
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
for (int i = 0; i < N; i++)
{
node *cursor2 = table[i];
while (cursor2 != NULL)
{
//creates a temp node
node *temp = cursor2;
cursor2 = cursor2->next;
free(temp);
}
table[i] = NULL;
}
printf("successful unload. \n");
return true;
}