I am able to compile the program, but what happens when I run it is that all the words in the text file will be printed as MISSPELLED WORDS, and then I'll get a segmentation fault error message after the last word. I've looked through my code numerous times but I can't seem to find the problem. Any help would be greatly appreciated. Thank you.
For example, this is what I get when I run ./speller texts/ralph.txt
:
MISSPELLED WORDS
When
I
grow
up
.... (body of the rest of the text)
Ralph
Wiggum
Segmentation fault
I have also run valgrind
with help50
, and when I do I get:
==8037== Stack overflow in thread 1: can't grow stack to 0xffe801ff8
==8037==
==8037== Process terminating with default action of signal 11 (SIGSEGV)
==8037== Access not within mapped region at address 0xFFE801FF8
==8037== at 0x401714: clear (dictionary.c:192)
==8037== If you believe this happened as a result of a stack
==8037== overflow in your program's main thread (unlikely but
==8037== possible), you can try to increase the size of the
==8037== main thread stack using the --main-stacksize= flag.
==8037== The main thread stack size used in this run was 8388608.
==8037== Stack overflow in thread 1: can't grow stack to 0xffe801ff0
==8037==
==8037== Process terminating with default action of signal 11 (SIGSEGV)
==8037== Access not within mapped region at address 0xFFE801FF0
==8037== at 0x4A256B0: _vgnU_freeres (in /usr/lib/valgrind/vgpreload_core-amd64-linux.so)
==8037== If you believe this happened as a result of a stack
==8037== overflow in your program's main thread (unlikely but
==8037== possible), you can try to increase the size of the
==8037== main thread stack using the --main-stacksize= flag.
==8037== The main thread stack size used in this run was 8388608.
==8037==
==8037== HEAP SUMMARY:
==8037== in use at exit: 290,334,912 bytes in 1,296,138 blocks
==8037== total heap usage: 1,296,140 allocs, 2 frees, 290,336,048 bytes allocated
==8037==
==8037== LEAK SUMMARY:
==8037== definitely lost: 0 bytes in 0 blocks
==8037== indirectly lost: 0 bytes in 0 blocks
==8037== possibly lost: 0 bytes in 0 blocks
==8037== still reachable: 290,334,912 bytes in 1,296,138 blocks
==8037== suppressed: 0 bytes in 0 blocks
==8037== Reachable blocks (those to which a pointer was found) are not shown.
==8037== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==8037==
==8037== For counts of detected and suppressed errors, rerun with: -v
==8037== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "dictionary.h"
typedef struct node
{
bool is_word;
struct node *children[27];
}
node;
//initialize pointers; root is pointer to the root node, current is pointer to node being analyzed at the moment
node *root;
node *current;
// counter for number of words in dictioary
int words = 0;
// character buffer to hold key while it is added to trie
char word[45];
bool check(const char *word)
{
// set current to point to root node
current = root;
// iterate through each character of word
for (int i = 0; i < strlen(word); i++)
{
// if character is alphabetical
if (word[i] != '\'')
{
// and is equal to NULL, return false
if (current -> children[tolower(word[i]) - 'a'] == NULL)
return false;
// if not, move to next node
else
current = current -> children[tolower(word[i]) - 'a'];
}
// if character is an apostrophe
else
{
// if pointer is equal to NULL, return false
if (current -> children[26] == NULL)
return false;
else
current = current -> children[26];
}
}
// check to see if is_word is marked as true
if (current -> is_word == true)
return true;
else
return false;
}
bool load(const char *dictionary)
{
// open dictionary, return 1 if unable to open
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
fprintf(stderr,"Could not open file\n");
return false;
}
// allocate memory for the root node, return 2 if unable to allocate memory
root = malloc(sizeof(node));
if (root == NULL)
{
fprintf(stderr, "Could not allocate memory\n");
return false;
}
// initialize is_word to false and array elements to NULL, have the current node pointer point to where the root node pointer is pointing
else
{
root -> is_word = false;
for (int i = 0; i < 27; i++)
root -> children[i] = NULL;
current = root;
}
// read one word at a time from the dictionary and store word in array, until EOF is returned
while (fscanf(dict, "%s", word) != EOF)
{
// iterate through each letter in word string
for (int i = 0; i < strlen(word); i++)
{
// check to see if a new node needs to be created for i'th character of key
if ((word[i] != '\'' && current -> children[tolower(word[i]) - 'a'] == NULL) || (word[i] == '\'' && current -> children[26] == NULL))
{
// if value is equal to a letter, allocate memory for it
if (word[i] != '\'')
{
current -> children[tolower(word[i]) - 'a'] = malloc(sizeof(node));
if (current -> children[tolower(word[i]) - 'a'] == NULL)
{
fprintf(stderr, "Could not allocate memory");
return false;
}
// change current node pointer to point to the node that was just created
current = current -> children[tolower(word[i]) - 'a'];
}
// if the i'th element of the array is an apostrophe, allocate memory for it
else
{
current -> children[26] = malloc(sizeof(node));
if (current -> children[26] == NULL)
{
fprintf(stderr, "Could not allocate memory");
return false;
}
// change current node pointer to point to the node that was just created
current = current -> children[26];
}
// after all the letters of the key have been added, change is_word to be true
current -> is_word = false;
// initialize array of pointers to NULL
for (int j = 0; j < 27; j++)
current -> children[j] = NULL;
}
// if node already exists for i'th character of key, navigate through that node and change the value of the pointer for currrent
else
{
if (word[i] != '\'')
current = current -> children[tolower(word[i]) - 'a'];
else
current = current -> children[26];
}
}
// after the key has been inserted, change the value of is_word to true
current -> is_word = true;
// increase word count by 1
words++;
}
fclose(dict);
return true;
}
unsigned int size(void)
{
return words;
}
void clear(node *ptr)
{
// iterate through each pointer array
for (int i = 0; i < 27; i++)
{
//iterate through each pointer array in next node and so on, using recursive function
if (ptr -> children[i] != NULL)
clear(ptr -> children[i]);
}
free(ptr);
}
bool unload(void)
{
clear(root);
return true;
}