so currently my speller seems to be working, it matches the staff solution with the austinpowers.txt (correctly identifies that 644 words have been misspelled & works when using a small dictionary & a test text file)
However, when running check50 it fails all checks saying that there was no actual output - i'm not sure where to go from here, i've looked online at reducing load time, changing little bits in the code but have come up unsuccessful so far. Any help would be much appreciated. Thanks guys!
:) dictionary.c, dictionary.h, and Makefile exist :) speller compiles :( handles most basic words properly expected "MISSPELLED WORD...", not "" :( handles min length (1-char) words expected "MISSPELLED WORD...", not "" :( handles max length (45-char) words expected "MISSPELLED WORD...", not "" :( handles words with apostrophes properly expected "MISSPELLED WORD...", not "" :( spell-checking is case-insensitive expected "MISSPELLED WORD...", not "" :( handles substrings properly expected "MISSPELLED WORD...", not ""
Here's the check50:
https://cs50.me/checks/2607aa8d0c8ab84b41bcf0ed7c981c8e8ace84e6
& here's the code:
/**
* Implements a dictionary's functionality.
*/
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "dictionary.h"
#define DICTIONARYSMALL "dictionaries/small"
#define DICTIONARY "dictionaries/large"
#define BUCKETSIZE 5000
// define word
char word[LENGTH + 1];
// hash function, uses multiplication.
int hash(const char *word)
{
unsigned int index = 0;
for (int i=0, n=strlen(word); i<n; i++) {
index = (index << 2) ^ word[i];
}
return index % BUCKETSIZE;
}
// defining the type node, to be used for linked list'
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// size of hashtable (which will be size of the alphabet)
node *hashtable[BUCKETSIZE];
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char *word)
{
char new_word[strlen(word)];
strcpy(new_word, word);
for (int i = 0; new_word[i] != '\0'; i++)
{
new_word[i] = tolower(new_word[i]);
}
for (int i = 0; word[i] != '\0'; i++)
{
if (!isalpha(word[i]) && word[i] != '\'')
{
return false;
}
}
// cursor which points to the first entry in hashtable index
int index = hash(new_word);
node *cursor = hashtable[index];
while (cursor != NULL)
{
if (strcmp(cursor->word, new_word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char *dictionary)
{
// get all arrays in dictionary to initialize to NULL
for (int i = 0; i < BUCKETSIZE; i++)
{
hashtable[i] = NULL;
}
node *head = NULL;
// open our dictionary tru
FILE *file = fopen(DICTIONARY, "r");
while(fscanf(file, "%s", word) != EOF)
{
// new node - will use chaining to solve issue if two data types end up in same bucket
node *new_node = malloc(sizeof(node));
// check to make sure node has shiz in it.
if (new_node == NULL)
{
unload();
return false;
}
strcpy(new_node->word, word);
int index = hash(new_node->word);
// case for if hashtable[i] is not pointing to any current word (linked list is empty in that array)
if (hashtable[index] == NULL)
{
head = hashtable[index];
hashtable[index] = new_node;
new_node->next = NULL;
}
// case for when hashtable[i] is pointing to word, i.e. wanna insert new item into linked list
else if (hashtable[index] != NULL)
{
new_node->next = hashtable[index];
hashtable[index] = new_node;
}
if (feof(file))
{
break;
}
}
fclose(file);
return true;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
int words = 0;
FILE *file = fopen(DICTIONARY, "r");
while(fscanf(file, "%s", word) != EOF)
{
words++;
}
return words;
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
node *cursor = hashtable[0];
for (int i = 0; i < BUCKETSIZE; i++)
{
cursor = hashtable[i];
while (cursor != NULL)
{
node* temp = cursor;
cursor = cursor->next;
free(temp);
}
}
return true;
}