Pset5 - Speller : all words in the text MISSPELLED - c

I've been stuck with this pset for more then a week now and can't seems to get any closer to getting something out of my code. I keep getting all the words in the text misspelled and I really don't understand how to create a hash function myself (I'm guessing the issue mostly comes from this but I'm not sure either...). I wanted to create a hash table with the first two letters of each words (it is inspired from various options I saw online).
Can someone help me understand what I'm doing wrong...
Thanks in advance !
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Choose number of buckets in hash table
const unsigned int N = 676;
// Hash table
node *table[N];
// Initialize new variables used in the program
unsigned int numberofwords;
unsigned int hashvalue;
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// Hash the word to determine its hash value
hashvalue = hash(word);
// Set cursor to the head of the linked list of the word
node* cursor = table[hashvalue];
// Traverse into the linked list comparing the word to find a correspondance while the cursor isn't pointing to null
while (cursor != NULL)
{
if (strcasecmp(cursor->word, word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// Inittialize a variable to keep track of the total of ASCII values
unsigned int sum = 0;
// Loop in all the letters in the word
for (int i = 0 ; i < strlen(word) ; i++)
{
// Ignore digits
if (word[i] != isalpha(word[i]))
{
continue;
}
else
{
// Check the first two characters in the word while setting them to lower letters in order to get they ASCII value
sum += 26 * (tolower(word[0]) - 'a') + (tolower(word[1]) - 'a');
}
// Divide the total of the three letters by the number of buckets
hashvalue = sum % N;
}
return hashvalue;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// Open the file
FILE* file = fopen(dictionary, "r");
char word[LENGTH + 1];
if (file == NULL)
{
fclose(file);
perror("Loading error");
return false;
}
else
{
// While dictionary doesn't return EOF, read strings from the file, one at the time
while (fscanf(file, "%s", word) != EOF)
{
// Create a new node for the word and copy it in the node
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
strcpy (n->word, "%s");
// Hash word to obtain a hash value
hashvalue = hash(word);
// Insert word into hash table depending if it's the first word or not
if (table[hashvalue] != NULL)
{
n->next = table[hashvalue];
}
else
{
n->next = NULL;
}
table[hashvalue] = n;
// Add one to the counter
numberofwords++;
}
fclose(file);
// Return true
return true;
}
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// Return the number of words we're keeping track of while loading the dictionary
return numberofwords;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// Check all the head of the hash table
for(int i = 0; i < N; i++)
{
// Create a temporary node to not lose the rest of the linked list
node* cursor = table[i];
// Set the cursor to the next node while the temporary value remains at the inital location, then free it before to move to cursor
while(cursor != NULL)
{
node* tmp = cursor;
cursor = cursor->next;
free(tmp);
}
}
return true;
}
Here is the dictonary.h file :
// Declares a dictionary's functionality
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include <stdbool.h>
// Maximum length for a word
// (e.g., pneumonoultramicroscopicsilicovolcanoconiosis)
#define LENGTH 45
// Prototypes
bool check(const char *word);
unsigned int hash(const char *word);
bool load(const char *dictionary);
unsigned int size(void);
bool unload(void);
#endif // DICTIONARY_H

Related

CS50 PSET 5 (Speller): How do I get my dictionary to correctly check one letter words?

I explored the possibility that i'm skipping the last node in a linked list, but I can't find the error.
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
unsigned int COUNT = 0;
// TODO: Choose number of buckets in hash table
const unsigned int N = 7480;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
int checkhash;
char lowerword[LENGTH + 1];
// convert word to lower case
for (int i = 0; i <= strlen(word); i++)
{
lowerword[i] = tolower(word[i]);
}
//get hash number
checkhash = hash(lowerword);
//check if it's in dictionary
node *trav = table[checkhash]; // traversal pointer
while (trav != NULL)
{
if (!strcasecmp(word, trav->word))
{
return true;
}
trav = trav->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
unsigned int hash_num = 0;
for (int i = 0; i < strlen(word); i += 3)
{
hash_num += word[i] * word[2];
hash_num += i + 3 * i;
}
hash_num += 3435;
return hash_num % N;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
// • Open dictionary file
FILE *dp = fopen(dictionary, "r");
// • Read strings from file one at a time
if (dp == NULL)
{
printf("Error: Could not open dictionary\n");
return false;
}
// declaring needed variables
char word[LENGTH + 1];
while (fscanf(dp, "%s", word) != EOF) // call fscanf untill EOF is returned
{
// • Create a new node for each word
// • Use malloc
// • Remember to check if return value is NULL
// • Copy word into node using strcpy
node *newnode = malloc(sizeof(node));
if (newnode == NULL)
{
unload();
printf("There is insufficient memory to load dictionary\n");
return false;
}
strcpy(newnode->word, word);
// • Hash word to obtain a hash value
// • Use the hash function
// • Function takes a string and returns an index
int index = hash(word);
// • Insert node into hash table at that location
if (table[index] == NULL)
{
table[index] = newnode;
newnode->next = NULL;
}
else
{
newnode->next = table[index];
table[index] = newnode;
}
COUNT++;
}
fclose(dp);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
return COUNT;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
node *trav; // traversal pointers
node *tmp;
for (int i = 0; i < N; i++)
{
trav = table[i]; //next pointer in array
// recursively free list
while (trav != NULL)
{
tmp = trav;
trav = trav->next;
free(tmp);
}
}
// TODO
return true;
}
I have tried readjusting the check function for the last 2 hours with no luck. I don't think it is the hash function as I've parsed through it for a while without finding any logical errors. I'm nearly certain that the error will be found within check(). I can't wait to smack my forehead over a newbie error.
Here is the feedback I get from check50:
MISSPELLED WORDS
WORDS MISSPELLED: 0
WORDS IN DICTIONARY: 1
WORDS IN TEXT: 1
Actual Output:
MISSPELLED WORDS
a
WORDS MISSPELLED: 1
WORDS IN DICTIONARY: 1
WORDS IN TEXT: 1

pset 5 speller, turning frowns upside down, programme can't handle most basic words or chars

the task is to create a fully functioning spell check, I think I have more than one error in my code which is causing lots of difficulty when trying to wrap my head round what exactly is causing all the frowns on check50. check50 only says my code compiles, everything else is a frown, I think my programme could be exiting during the check function as size and unload have no runtime. I also get exit code 1 once run, however I may be wayyy off as this is my first programming course. Any tips, help or pointers in the right direction would be massivly appriciated!
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
#include "dictionary.h"
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
} node;
// TODO: Choose number of buckets in hash table
const unsigned int N = 1000;
// Hash table
node *table[N];
bool check(const char *word)
{
// hash word
int x = hash(word);
// create cursor, set to first item in linked list
node *cursor = table[x];
// loop over hash tables
while (cursor != NULL)
{
if (strcasecmp(word, cursor->word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
int dictionary_size = 0; // global variable for size of dictionary, used in multiple functions
unsigned int hash(const char *word)
{
int value = 0;
// hash function using math of all leters
// loop over every word
for (int i = 0; i < strlen(word); i++)
{
// convert to lower case for ascii values, removes case sensitive problem
value += tolower(word[i]); // sum of ascii values of word
}
return value % N; // return index for word
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
// array to store words from dictionary
char word[LENGTH + 1];
// open dictionary file
FILE *d = fopen(dictionary, "r");
if (d == NULL)
{
return false;
}
// read strings from file repeat for each word in dictionary , similar loop to recover.c
while (fscanf(d, "%s", word) != EOF)
{
// keep track of dictionary size
dictionary_size++;
// create new node
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
// store word in array
strcpy(n->word, word);
n->next = NULL;
// hash word
int x = hash(word);
// set pointers to correct order
n->next = table[x];
table[x] = n;
}
fclose(d);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
return dictionary_size;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// loop over hash tables
for (int j = 0; j < N; j++)
{
// initialise cursor for local scope
node *cursor = table[j];
// traverse linked list
while (cursor != NULL)
{
node *tmp = cursor;
cursor = cursor->next;
free(tmp);
return true;
}
}
return false;
}
From comments:
in regards to the frowns the only one i have now is: :( programme is free of memory errors. check50 was saying everything was wrong, could've been an error with it
The unload function frees one node and then returns (to the call from speller). The function should not return until it has freed all the nodes (ie finished the while loop).

When I run the program, it shows "killed". How do I overcome this issue?

This is regarding pset5 speller, and below is my code. When I run it, it shows "killed" in my terminal. Moreover, when I try to debug it or try valgrind, the program just stops and exits. How do I overcome this issue?
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// TODO: Choose number of buckets in hash table
const unsigned int N = 150000;
// Hash table
node *table[N];
//Declare variables here so that they can be used in the different functions below
unsigned int HASH_INDEX;
unsigned int NO_OF_WORDS = 0;
node *CURSOR;
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
HASH_INDEX = hash(word);
CURSOR = table[HASH_INDEX];
do
{
if (strcasecmp(CURSOR->word, word) == 0)
{
return true;
}
else
{
CURSOR = CURSOR->next;
}
}
while (CURSOR != NULL);
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO: Improve this hash function
// close address, each bucket in the hash table is a pointer
unsigned int hash_value = 0;
for (int i = 0; i < strlen(word); i++)
{
int c = tolower(word[i]);
hash_value = hash_value + c;
}
hash_value = hash_value % 31;
return hash_value;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
// open dictionary file
//use fopen
//remember to check if return value is NULL, to make sure we can successfully open up the file. If can't open then return false
FILE *d = fopen(dictionary, "r");
if (d == NULL)
{
return false;
}
// read strings from file one at a time (one word in the dictionary at a time)
//fscanf(file, "%s", word) --> %s means want to read in a string, word is char array a place we reading the word into.
//need to keep looping this fscanf for every word in the dictionary until fscanf return EOF (once it reaches the end of file)
char word[LENGTH + 1];
while (fscanf(d, "%s", word) != EOF)
{
// create a new node for each word, a node that contains a value and the next pointer (this helps to store each word into the hash table)
//use malloc to store a new node
//remember to check if return value is NULL --> check whether malloc returns NULL or not becos if malloc does not have enough memory it will return NULL and our load function should return false
//copy word into node using strcpy --> it takes a string and copy it from one location into another location
node *w = malloc(sizeof(node));
if (w == NULL)
{
return false;
}
else
{
strcpy(w->word, word);
w->next = NULL;
// hash word using the hash function to obtain a hash value
//use the hash function defined in dictionary.c --> function takes a string and returns an index (to determine which index into the hash table we should use when inserting this node)
HASH_INDEX = hash(word);
// lastly, take each of those words and insert that node into the hash table at the location given by hash functon
//recall that hash table is an array of linked lists
//be sure to set pointers in the correct order --> point to the 2nd node first then shift the head to point to the new node
if (table[HASH_INDEX] == NULL)
{
table[HASH_INDEX] = w;
}
w->next = table[HASH_INDEX];
table[HASH_INDEX] = w;
NO_OF_WORDS++;
}
}
fclose(d);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
return NO_OF_WORDS;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
for (int i = 0; i < N; i++)
{
CURSOR = table[i];
while (CURSOR != NULL)
{
node *tmp = CURSOR;
CURSOR = CURSOR->next;
free(tmp);
}
}
return true;
}
Would really appreciate it if someone could help me with this! Thank you in advance!

My program of speller.c is not compiling pset5

When I run my program i get these 2 errors and not sure why
The error
dictionary.c:87:9: error: use of undeclared identifier 'words_counter'
words_counter++;
^
dictionary.c:97:12: error: use of undeclared identifier 'words_counter'
return words_counter;
^
2 errors generated.
make: *** [Makefile:3: speller] Error 1
The code
// Implements a dictionary's functionality
#include <stdbool.h>
#include "dictionary.h"
#include <stdlib.h>
#include <strings.h>
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.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 = 1500;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
int index = hash(word);
node *cursor = table[index];
while (cursor != NULL)
{
if (strcasecmp(word, cursor -> word) ==0 )
{
return true;
}
//Move cursor to next node
cursor = cursor -> next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO
// Ref of hash function: https://cs50.stackexchange.com/questions/38753/cs50-good-hash-function-for-pset5-speller/38755
int hash = 600;
while (*word != '\0')
{
hash = ((hash << 4 ) + (int) (*word)) % N;
word++;
}
return hash % N;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
FILE *file = fopen(dictionary, "r");
if (file == NULL)
{
return false;
}
// Read strings from file
// define word
char word [LENGTH + 1];
int index;
while(fscanf(file, "%s", word) != EOF)
{
// Creating new node
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
// Copies word to the node
strcpy (n->word, word);
// Obtaining index to hash word
index = hash(word);
n -> next = table[index];
table[index] = n;
words_counter++;
}
fclose(file);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
return words_counter;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
//Free nodes in each linked list
for (int i = 0; i<N; i++)
{
node *cursor = table[i];
node *tmp = cursor;
while (cursor != NULL)
{
cursor = cursor-> next;
free (tmp);
tmp = cursor;
}
}
return true;
}
I defined words_counter and it compiled but it seems I did not pass check50 by 2 mistakes:
the code
// Implements a dictionary's functionality
#include <stdbool.h>
#include "dictionary.h"
#include <stdlib.h>
#include <strings.h>
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.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 = 1500;
unsigned words_counter;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
int index = hash(word);
node *cursor = table[index];
while (cursor != NULL)
{
if (strcasecmp(word, cursor -> word) == 0 )
{
return true;
}
//Move cursor to next node
cursor = cursor -> next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO
// Ref of hash function: https://cs50.stackexchange.com/questions/38753/cs50-good-hash-function-for-pset5-speller/38755
int hash = 600;
while (*word != '\0')
{
hash = ((hash << 4 ) + (int) (*word)) % N;
word++;
}
return hash % N;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
FILE *file = fopen(dictionary, "r");
if (file == NULL)
{
return false;
}
// Read strings from file
// define word
char word [LENGTH + 1];
int index;
while(fscanf(file, "%s", word) != EOF)
{
// Creating new node
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
// Copies word to the node
strcpy (n->word, word);
// Obtaining index to hash word
index = hash(word);
n -> next = table[index];
table[index] = n;
words_counter++;
}
fclose(file);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
return words_counter;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
//Free nodes in each linked list
for (int i = 0; i<N; i++)
{
node *cursor = table[i];
node *tmp = cursor;
while (cursor != NULL)
{
cursor = cursor-> next;
free (tmp);
tmp = cursor;
}
}
return true;
}
the mistakes:
:) dictionary.c exists
:) speller compiles
:( handles most basic words properly
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:) handles min length (1-char) words
:) handles max length (45-char) words
:) handles words with apostrophes properly
:( spell-checking is case-insensitive
expected "MISSPELLED WOR...", not "MISSPELLED WOR..."
:) handles substrings properly
:) program is free of memory errors
I am not sure how to handle these 2
Your words_counter is used as the global variable in your code, so define it in the same place as other global objects:
const unsigned int N = 1500;
unsigned words_counter;

Segmentation fault in CS50 Speller. Why?

I am working on the CS50 pset5 Speller, and I keep getting a segmentation fault error. Debug50 suggests the problem is the line n->next = table[index]; in the implementation of the load function, line 110. I tried to revise but I can´t figure out why it would give error. Here below my code, can anyone please help me?
// Implements a dictionary's functionality
#include <stdbool.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.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 = 150000;
// Nodes counter
int nodes_counter = 0;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
int hash_value = hash(word);
node *cursor = malloc(sizeof(node));
if (cursor != NULL)
{
cursor = table[hash_value];
}
if (strcasecmp(cursor->word, word) == 0) // If word is first item in linked list
{
return 0;
}
else // Iterate over the list by moving the cursor
{
while (cursor->next != NULL)
{
if (strcasecmp(cursor->word, word) == 0) // If word is found
{
return 0;
}
else
{
cursor = cursor->next;
}
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
// Adaptation of FNV function, source https://www.programmingalgorithms.com/algorithm/fnv-hash/c/
const unsigned int fnv_prime = 0x811C9DC5;
unsigned int hash = 0;
unsigned int i = 0;
for (i = 0; i < strlen(word); i++)
{
hash *= fnv_prime;
hash ^= (*word);
}
return hash;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// Open Dictionary File (argv[1] or dictionary?)
FILE *file = fopen(dictionary, "r");
if (file == NULL)
{
printf("Could not open file\n");
return 1;
}
// Read until end of file word by word (store word to read in word = (part of node)?)
char word[LENGTH + 1];
while(fscanf(file, "%s", word) != EOF)
{
// For each word, create a new node
node *n = malloc(sizeof(node));
if (n != NULL)
{
strcpy(n->word, word);
//Omitted to avoid segmentation fault n->next = NULL;
nodes_counter++;
}
else
{
return 2;
}
// Call hash function (input: word --> output: int)
int index = hash(word);
// Insert Node into Hash Table
n->next = table[index];
table[index] = n;
}
return false;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// Return number of nodes created in Load
if (nodes_counter > 0)
{
return nodes_counter;
}
return 0;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
for (int i = 0; i < N; i++)
{
node *cursor = table[i];
while (cursor->next != NULL)
{
node *tmp = cursor;
cursor = cursor->next;
free(tmp);
}
}
return false;
}
There are multiple problems in your code:
node *table[N]; cannot be only be defined as a global object if N is a constant expression. N is defined as a const unsigned int, but N is not a constant expression in C (albeit it is in C++). Your program compiles only because the compiler accepts this as a non portable extension. Either use a macro or an enum.
you overwrite cursor as soon as it is allocated in check(). There is no need to allocate a node in this function.
the hash() function should produce the same hash for words that differ only in case.
the hash() function only uses the first letter in word.
the hash() function can return a hash value >= N.
fscanf(file, "%s", word) should be protected agains buffer overflow.
you do not check if cursor is non null before dereferencing it in unload()
Here is a modified version:
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.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
enum { N = 150000 };
// Nodes counter
int nodes_counter = 0;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word) {
int hash_value = hash(word);
// Iterate over the list by moving the cursor
for (node *cursor = table[hash_value]; cursor; cursor = cursor->next) {
if (strcasecmp(cursor->word, word) == 0) {
// If word is found
return true;
}
}
// If word is not found
return false;
}
// Hashes word to a number
unsigned int hash(const char *word) {
// Adaptation of FNV function, source https://www.programmingalgorithms.com/algorithm/fnv-hash/c/
unsigned int fnv_prime = 0x811C9DC5;
unsigned int hash = 0;
for (unsigned int i = 0; word[i] != '\0'; i++) {
hash *= fnv_prime;
hash ^= toupper((unsigned char)word[i]);
}
return hash % N;
}
// Loads dictionary into memory, returning true if successful, else a negative error number
int load(const char *dictionary) {
// Open Dictionary File (argv[1] or dictionary?)
FILE *file = fopen(dictionary, "r");
if (file == NULL) {
printf("Could not open file\n");
return -1;
}
// Read until end of file word by word (store word to read in word = (part of node)?)
char word[LENGTH + 1];
char format[10];
// construct the conversion specifier to limit the word size
// read by fscanf()
snprintf(format, sizeof format, "%%%ds", LENGTH);
while (fscanf(file, format, word) == 1) {
// For each word, create a new node
node *n = malloc(sizeof(node));
if (n == NULL) {
fclose(file);
return -2;
}
strcpy(n->word, word);
n->next = NULL;
nodes_counter++;
// Call hash function (input: word --> output: int)
int index = hash(word);
// Insert Node into Hash Table
n->next = table[index];
table[index] = n;
}
fclose(file);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void) {
// Return number of nodes created in Load
return nodes_counter;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void) {
for (int i = 0; i < N; i++) {
node *cursor = table[i];
table[i] = NULL;
while (cursor != NULL) {
node *tmp = cursor;
cursor = cursor->next;
free(tmp);
}
}
return true;
}

Resources