0

When I compile and run speller, I get the following from the terminal:

dictionary.o: In function check': /home/ubuntu/workspace/pset5/speller/dictionary.c:51: undefined reference tohashValue' dictionary.o: In function load': /home/ubuntu/workspace/pset5/speller/dictionary.c:114: undefined reference tohashValue' clang: error: linker command failed with exit code 1 (use -v to see invocation)

This is my code for dictionary.c:

/**
 * Implements a dictionary's functionality.

*/

#include <stdbool.h>

#include "dictionary.h"

//Declaration of data structure node
typedef struct node
{
    char word[LENGTH + 1];
    struct node* next;
}
node;

//Declaration of node pointer to hashtable
node* hashTable[HASHTABLESIZE];

//Tracking number of words in dictionary
int wordCount = 0;

//Variable to track loading and unloading of dictionary
bool loaded = false;

//declaration of hash function; credits: 
https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/
inline int hashValue(const char* word)
{
    unsigned int hash = 0;

    for(int i = 0, n = strlen(word); i < n; i++)
    {
        hash = (hash<<2)^word[i];
    }
    return hash % HASHTABLESIZE;
}

/**
 * Returns true if word is in dictionary else false.
 */
bool check(char* word)
{

    //ensure that the whole word is in lowercase
    for(int k =0, n = strlen(word); k < n; k++)
    {
        word[k] = tolower(word[k]);
    }

    //getting the index of hash table(bucket) with word
    int index = hashValue(word);
    //declaration of node pointer head
    node* head = NULL;

    //cursor and head point to first node of linked list in that bucket
    node* cursor = head = hashTable[index];

    //find for word in the linked list
    while(hashTable[index] != NULL)
    {
        //compare both strings
        if(strcasecmp(cursor->word, word) == 0)
        {
            return true;
        }
        //keep traversing list to find the word
        cursor = cursor->next;

    }

   return false;
}

/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char *dictionary)
{
    //opening dictionary file to read
    FILE* file = fopen(dictionary, "r");
    //declaration of word
    char word[LENGTH+1];
    //checking dictionary file for NULL
    if(file == NULL)
    {
        fprintf(stderr, "Could not open %s.\n", dictionary);
        return false;
    }

    //ensuring indexes of hash table are empty
    for(int i =0; i < HASHTABLESIZE; i++)
    {
        hashTable[i] = 0;
    }

    //scanning dictionary file word by word
    while(fscanf(file, "%s", word)!=EOF)
    {
        //creation of a new node
        node* newNode = malloc(sizeof(node));
        //checking node pointer for NULL
        if(newNode == NULL)
        {
            unload();
            return false;
        }

    //insertion of word into node
    strcpy(newNode->word, word);
    newNode->next = NULL;
    //increase word count
    wordCount++;
    //generation of index of hash table into which node is to be chained to (hash function)
    int index = hashValue(word);

    //ensure index of hash table is empty
    if(hashTable[index] == NULL)
    {
        hashTable[index] = newNode;
    }
    //if index of hash table already has node attached to it
    else
    {
        newNode->next = hashTable[index];
        hashTable[index] = newNode;
    }

}

fclose(file);
loaded = true;
return true;
}

/**
 * Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
    //When dictionary is loaded, return the count of words in dictionary
    if(loaded)
    {
        return wordCount;
    }  
    //If not, execute exit code
    else
    {
        return 0;
    }

}

/**
* Unloads dictionary from memory. Returns true if successful else false.
 */
bool unload(void)
{
    //Entering each bucket of hash table
    for(int j = 0; j < HASHTABLESIZE; j++)
    {
        while(hashTable[j] != NULL)
        { 
            node* cursor = hashTable[j];
            //Freeing linked lists
            while(cursor != NULL)
            {
                node* temp = cursor;
                cursor = cursor->next;
                free(temp);
            }

        }
    }
    loaded = false;
    return false;

}

I believe that there is an incorrect implementation on my part with the hashValue function but I am unsure where I went wrong. I would really appreciate it if a kind soul could explain to me where I'm wrong :)

1

inline int hashValue(const char* word)

Not sure why you have inline there, but remove that and it should compile fine.

Secondly, looks like you changed the declaration of check. It needs to be

bool check(const char *word)

You can't change word, so you'll need to create a temporary char array to hold your lowercase version. Once you do that, then you can use strcmp instead.

5
  • Thank you for your help, the code compiled and ran but it says segmentation fault in the line of code in check where I implemented strcasecmp. Is there something wrong with my implementation?
    – Prav Elan
    Jan 5 '18 at 12:55
  • see my updated answer.
    – curiouskiwi
    Jan 6 '18 at 2:18
  • Thank you for your kind reply :) Really sorry to bother you again, but I ran valgrind and it appears that there is something wrong with my implementation of unload function. Am I doing something wrong?
    – Prav Elan
    Jan 7 '18 at 11:38
  • return false; why are you returning false?
    – curiouskiwi
    Jan 7 '18 at 19:12
  • Ahh, I see where I went wrong. Thank you for your help and sorry for the late acknowledgement.
    – Prav Elan
    Jan 21 '18 at 12:05

You must log in to answer this question.

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