Spell checker program, check function speller cs50 - c

This program works as a spell checker, it reads a dictionary file to load into the hash table, then reads another text file that will be read and will check every word if it is in the hash table, if not then it is considered a misspelled word. All of my functions seem to work except for my check function, when I run it the number of misspelled words is always the same as the number of words in text. This was working before but I changed the hash function because this hash function was said to be better to assign the values into unique index, but after changing just the hash function the check function doesn't work anymore.
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.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 = 200000;
// Hash table
node *table[N];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
// TODO
int len = strlen(word);
char copy[len + 1];
// change into lowercase the word
for (int i = 0; i != '\0'; i++)
{
copy[i] = tolower(word[i]);
}
// get the index by using the hash function
int index = hash(copy);
if (table[index] == NULL)
{
return false;
}
node *tmp = table[index];
// check if the word is in the hash table
while (tmp != NULL)
{
if (strcmp(tmp->word, copy) == 0)
{
return true;
}
tmp = tmp->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
/* credits to...
*https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/
*/
unsigned int hash = 0;
for (int i = 0, n = strlen(word); i < n; 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
char *words = malloc(sizeof(char) * (LENGTH + 1));
if (words == NULL)
{
return 1;
}
// initialize the hash table to NULL
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
// open dictionary file
FILE *indata = fopen(dictionary, "r");
// 1 character for '\0' and another for '\n' because fgets takes a trailing new line
// when it reads 'man' the value of words will be "man\n\0" so meaning 2 extra characters
while (fgets(words, LENGTH + 2, indata) != NULL)
{
// get the index by using the hash function
int index = hash(words);
// allocate memory for the newNode
node *newNode = malloc(sizeof(node));
if (newNode == NULL)
{
return false;
}
// get rid of the trailing new line from fgets
words[strlen(words) - 1] = '\0';
strcpy(newNode->word, words);
// make the newNode the head of the list
newNode->next = table[index];
table[index] = newNode;
}
// free memory and close the opened file
free(words);
fclose(indata);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
// TODO
// counter of words loaded
unsigned int counter = 0;
// loop through the hash table
for (int i = 0; i < N; i++)
{
node *tmp = table[i];
while (tmp != NULL)
{
counter++;
tmp = tmp->next;
}
}
return counter;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
// TODO
// loop through the whole hash table
for (int i = 0; i < N; i++)
{
while (table[i] != NULL)
{
node *tmp = table[i]->next;
free(table[i]);
table[i] = tmp;
}
}
return true;
}

There are multiple problems in your code:
The definition node *table[N]; is invalid in C because N must be a compile time constant expression. const unsigned int N = 200000; fits this constraint in C++, but not in C. N must be a macro or an enum definition.
in check(), the loop to copy the string as lowercase is incorrect: for (int i = 0; i != '\0'; i++) should be for (int i = 0; word[i] != '\0'; i++)
in check() you do not null terminate the string you build in copy. copy is allocated with malloc(), it is uninitialized, so the null terminator must be set explicitly.
the char argument in tolower(word[i]) must be cast as tolower((unsigned char)word[i]) to avoid undefined behavior on negative char values, should the char be signed on your platform.
in load(), the words array is allocated with a length of LENGTH+1 bytes, but you pass LENGTH+2 to fgets as the buffer size, causing potential undefined behavior if the dictionary contains a line with LENGTH characters.
in load(), hash(words) is called before stripping the newline at the end of the line. Hence the hash code is incorrect and the word will not be found in the dictionary because it is stored in the wrong bucket.
Here is a modified version:
// Implements a dictionary's functionality
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node {
struct node *next;
char word[LENGTH + 1];
} node;
// Number of buckets in hash table
#define HASH_SIZE 200000
// Hash table
node *table[HASH_SIZE];
// Hashes word to a number
unsigned int hash(const char *word) {
/* credits to...
*https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/
*/
unsigned int hash = 0;
for (int i = 0; word[i] != '\0'; i++) {
hash = (hash << 2) ^ word[i];
}
return hash % HASH_SIZE;
}
// Returns true if word is in dictionary else false
bool check(const char *word) {
char copy[LENGTH + 1];
int i, len = strlen(word);
if (len > LENGTH)
return false;
// change into lowercase the word
for (i = 0; word[i] != '\0'; i++) {
copy[i] = (char)tolower((unsigned char)word[i]);
}
copy[i] = '\0';
// get the index by using the hash function
int index = hash(copy);
// check if the word is in the hash table
for (node *tmp = table[index]; tmp != NULL; tmp = tmp->next) {
if (strcmp(tmp->word, copy) == 0) {
return true;
}
}
return false;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary) {
// 1 character for '\0' and another for '\n' because fgets takes a trailing new line
// when it reads 'man' the value of words will be "man\n\0" so meaning 2 extra bytes
char words[LENGTH + 2];
// open dictionary file
FILE *indata = fopen(dictionary, "r");
if (indata == NULL)
return false;
while (fgets(words, sizeof words, indata) != NULL) {
// get rid of the trailing new line from fgets
words[strcspn(words, "\n")] = '\0';
// allocate memory for the newNode
node *newNode = malloc(sizeof(node));
if (newNode == NULL) {
fclose(indata);
return false;
}
strcpy(newNode->word, words);
// get the index by using the hash function
int index = hash(words);
// make the newNode the head of the list
newNode->next = table[index];
table[index] = newNode;
}
// close the opened file
fclose(indata);
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void) {
// counter of words loaded
unsigned int counter = 0;
// loop through the hash table
for (int i = 0; i < HASH_SIZE; i++) {
for (node *tmp = table[i]; tmp != NULL; tmp = tmp->next) {
counter++;
}
}
return counter;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void) {
// loop through the whole hash table
for (int i = 0; i < HASH_SIZE; i++) {
while (table[i] != NULL) {
node *next = table[i]->next;
free(table[i]);
table[i] = next;
}
}
return true;
}

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

Cs50 pset5 - program crashing

I finished writing my code for speller. It compiles fine but the only output being printed is "Misspelled words". The words misspelled , words in text, words in dictionary does not get printed. I'm assuming its because the program crashes before then? Here is my code. If only I knew in which function or area my problem lies I might be able to fix it. Also, my hash function is to base hash indexes base on the first two letters of the word.
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dictionary.h"
int dsize = 0;
// 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 = 676;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
// hash word
int hashnumber = hash(word);
node *cursor = table[hashnumber];
// traversing linked list at that hash number
while(cursor != NULL)
{
if((strcasecmp(cursor->word, word) == 0))
{
return true;
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
int hash;
// TODO: Improve this hash function
for( int i = 97; i < 123; i ++)
{
hash = (i - 97) * 26;
// check asciivalue both uppercase and lowercase for first letter
if(word[0] == (char)i || word[0] == (char)(i - 32) )
{
for ( int j = 97; j < 122; j++)
{
// check asciivalue both uppercase and lowercase for second letter
if(word[1] == (char)j || word[1] == (char)(j - 32))
{
hash = hash + (j - 97);
}
}
}
}
return hash;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
for( int i = 0; i < N; i++)
{
table[i] = NULL;
}
FILE *input = fopen(dictionary, "r");
if (dictionary== NULL)
{
return false;
}
node *temp;
char word[LENGTH + 1];
while((fscanf(input, "%s", word)) != EOF)
{
temp = malloc(sizeof(node));
if(temp == NULL)
{
return false;
}
strcpy(temp->word, word);
int hashnumber = hash(word);
if (table[hashnumber] == NULL)
{
table[hashnumber] = temp;
}
else
{
temp->next = table[hashnumber];
table[hashnumber] = temp;
}
dsize++;
}
fclose(input);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
return dsize;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
node *temp;
node *cursor;
for ( int i = 0; i < N; i++ )
{
cursor = table[i];
while(table[i] != NULL)
{
temp = cursor;
cursor = cursor->next;
free(temp);
}
if(cursor == NULL && i == (N - 1))
{
return true;
}
}
return false;
}

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;
}

cs50 speller problem hash table doesn't seem to form in load function

currently doing the speller problem of cs50 pset5.
I'm having a trouble with forming the hash table and i think it causes a segmentation fault later on when i try to run a function that searches the table.
this is the function that creates the hash table:
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r"); //opens dictionary file
if (dict == NULL) // if cant be opened loading failed
{
return false;
}
char w[LENGTH + 1]; //buffer (length is the maximum character number
int i = 0; //index within word
while(fscanf(dict, "%s", w) != EOF) // scanning the dictionary for words
{
int x = hash(w); //getting the number of the linked list within the table
node *n = malloc(sizeof(node)); //allocating memory for a new node
if (n == NULL)
{
return false;
}
for (int j = 0; j < strlen(w) + 1; j++) // documenting the word within the new node
{
n->word[i] = w[j];
}
n->next = table[x];
table[x] = n; //new node is the beginning of the linked list
dicsize++;
}
fclose(dict);
return true;
}
my main question is whether my code for forming the table is correct and if not then why
thank you in advance
and this is the entire code:
// Implements a dictionary's functionality
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.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 = 26;
int dicsize = 0;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
int x = hash(word);
node *cur = table[x];
while(table[x] != NULL)
{
if(strcasecmp(word, cur->word) == 0)
{
return true;
}
if(cur == NULL)
{
return false;
}
cur = cur->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
char temp = tolower(word[0]);
int place = (temp - 97);
return place;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r"); //opens dictionary file
if (dict == NULL) // if cant be opened loading failed
{
return false;
}
char w[LENGTH + 1]; //buffer
int i = 0; //index within word
while(fscanf(dict, "%s", w) != EOF) // scanning the dictionary for words
{
int x = hash(w); //getting the number of the linked list within the table
node *n = malloc(sizeof(node)); //allocating memory for a new node
if (n == NULL)
{
return false;
}
for (int j = 0; j < strlen(w) + 1; j++) // documenting the word within the new node
{
n->word[i] = w[j];
}
n->next = table[x];
table[x] = n; //new node is the beginning of the linked list
dicsize++;
}
fclose(dict);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
printf("%i", dicsize);
return dicsize;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
return false;
}
The likely culprit is
for (int j = 0; j < strlen(w) + 1; j++) // documenting the word within the new node
{
n->word[i] = w[j];
}
As i is not changing inside the loop, instead of copying the string it will dump all the chars into one. The other index should also be j. (as in n->word[j] = w[j];)
It would be better to do this as strcpy anyway.

Pset5 Speller: I'm getting segmentation fault with small dictionary

When i used check50, my program was not giving any report as output. So i tried my code with small dictionary and i got a segmentation fault. I think it has do with my unload function
This is my code
// Implements a dictionary's functionality
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.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 = 125;
int word_size = 0;
// Hash table
node *hashtable[N];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
//Convert the word to lowercase
int length = strlen(word);
char copy[length + 1];
for (int i = 0; i < length; i++)
{
copy[i] = tolower(word[i]);
}
copy[length] = '\0';
//Find out the hash value
int hash_value = hash(copy);
node *tmp = hashtable[hash_value];
//Check if word is in dictionary
while(tmp != NULL)
{
if(strcasecmp(tmp->word, copy) == 0)
{
return true;
}
tmp = tmp->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
//It's djb2 hash function
unsigned int hash = 5381;
int c;
while ((c = *word++))
hash = ((hash << 5) + hash) + c;
return hash % N;
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
//Initialize all indexs of hastable to NULL
for(int i =0; i < LENGTH + 1; i++)
{
hashtable[i] = NULL;
}
char word[LENGTH +1];
int pos;
FILE *dict = fopen(dictionary,"r");
if(dict == NULL)
{
return false;
}
//Scan every word...I think my problem is in here
while (fscanf(dict, "%s", word) != EOF)
{
word_size++;
int length = strlen(word);
char copy[length + 1];
for (int i = 0; i < length; i++)
{
copy[i] = tolower(word[i]);
}
copy[length] = '\0';
node *new_node = malloc(sizeof(node));
strcpy(new_node->word,copy);
new_node->next = NULL;
//Find the hash value
pos = hash(copy);
//Set the pointer of the new node to index of hashtable
new_node->next = hashtable[pos];
hashtable[pos] = new_node;
}
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
return word_size;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
node *cursor = NULL;
node* tmp = NULL;
for(int i=0; i < N; i++)
{
while(cursor->next != NULL)
{
tmp = cursor;
cursor = cursor->next;
free(tmp);
}
free(cursor);
}
return true;
}
Can anyone say the write logic if my unload function is wrong. It works fine with large dictionary. I tried but couldn't figure out how to use debug50
In your unload () function you soon define
node *cursor = NULL;
but then, without assigning to cursor any other value, you dereference it:
while ( cursor->next != NULL )
Dereferencing a NULL pointer raises undefined behavior, and it will likely result in a segmentation fault.
The following action is free(cursor); that, with a NULL pointer, is not good as well.

Resources