0
// Implements a dictionary's functionality
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include "dictionary.h"

unsigned int sizee;
unsigned int *pointer = &sizee;

struct node* NodeFront(struct node *head, char *data);

// Represents a node in a hash table
typedef struct node
{
    char word[LENGTH + 1];
    struct node *next;
}
node;

//The Idea is making an array of 26 pointers to represent alphabetic characters each one will be the head of the linked list of words beginning
//with the same letter like A for example..


// Number of buckets in hash table
const unsigned int N = 26;

// Hash table
node *table[N] = {NULL};

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    int number = hash(word);
    node *temp = table[number];

    while(temp -> next != NULL)
    {
        if (strcasecmp(word, temp -> word) == 0)
        {
            return true;
        }

        temp = temp -> next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
   return (tolower(word[0])- 97);
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    char str[LENGTH + 1];
    unsigned int counter = 0;

    //open the dictionary to read data
    FILE *file = fopen(dictionary ,"r");

    //if couldn't read dictionary return false
    if (file == NULL)
    {
        printf("couldn't open dictionary \n");
        return false;
    }

    //read a line by line to get each word in the text
    while (fgets(str, LENGTH, file) != NULL)
    {
        int position = hash(str);
        if (table[position] == NULL)
        {
            node *n = malloc(sizeof(struct node));

            //if we couldn't allocate memory for the node
            if (n == NULL)
            {
                return false;
            }

            strcpy(n -> word, str);
            n -> next = NULL;
            table[position] = n;
            counter ++;
        }

        else
        {
            table[position] = NodeFront(table[position], str);
            counter ++;
        }
    }
    *pointer = counter;
    fclose(file);
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    return sizee;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    for (int i = 0; i < 26; i++)
    {
        while(table[i] != NULL)
        {
            node *tmp = table[i] -> next;
            free(table[i]);
            table[i] = tmp;
        }
    }
    return true;
}

struct node* NodeFront(struct node *head, char *data)
{
    node *n = malloc(sizeof(struct node));

    strcpy(n -> word, data);
    n -> next = head;

    return n;
}
  • When i run large dictionary, segmentation fault doesn't appear, despite check always returns fault, i have been debugging for about 2 days, but i don't find the answer, but the dictionary is load fine, as if i print temp->word of the table[0] which representats letter 'A' it prints all words beginning with letter A, so i don't know where is the problem – Mazen Nov 21 '20 at 18:07
  • 1
    @Diana, your comment makes no sense. It doesn't matter that the check function appears in the file before the load function. Both are called, in the proper order, from the code in speller.c. – Cliff B Nov 23 '20 at 0:06
  • @Diana sorry it isn't the problem solution, because when i print the linked list inside search function it works fine, but it still return false for all of the comparisons between the word and the linked list – Mazen Nov 24 '20 at 23:30
0

As most Segfaults, it usually is using an out-of-bounds index for an array or trying to access a member in a pointer pointing to NULL. So check for any usage of strut members in pointers that you didn't test for NULL

In your case, I believe the problem is in check(), most precisely here:

bool check(const char *word)
{
    int number = hash(word);
    node *temp = table[number];

    while(temp -> next != NULL)

You never tested if temp itself points to NULL before trying to use temp->next.

And when can temp be NULL? When table[number] == NULL, i.e., when you have an empty bucket. Which happens in the small dictionary (only 2 words, both starting with c), but not in the large dictionary.

Change your while() condition so it tests for temp itself, not temp->next. You're already assigning temp = temp->next in the end of the loop.

As for why check() is always returning false with the larger dictionary... well, it's a logic bug in the same while() condition. think about what happens when you assign temp = temp->next in the end of the loop and right away while() checks for temp->next != NULL. You're effectivelly skipping nodes!

  • i've updated what u said but it still says everyword isn't in the dictionary ,bool check(const char *word) { int number = hash(word); node *temp = table[number]; while(temp != NULL) { if (strcasecmp(word, temp -> word) == 0) { return true; } temp = temp -> next; } return false; } this is the code update in check function @MestreLion – Mazen Dec 21 '20 at 20:11
  • @Mazen: Is the Segfault issue solved at least? You can edit your own question to update the code to your current version – MestreLion Dec 28 '20 at 0:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .