0

Every time I compile speller (hash table) I get these errors:

clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o speller.o speller.c
clang -fsanitize=signed-integer-overflow -fsanitize=undefined -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wshadow -c -o dictionary.o dictionary.c
dictionary.c:34:16: error: array type 'char [46]' is not assignable
    nNode.word = word;
    ~~~~~~~~~~ ^
dictionary.c:36:18: error: indirection requires pointer operand ('node' (aka 'struct node') invalid)
    &list.next = *nNode;
                 ^~~~~~
dictionary.c:84:14: error: initializing 'node' (aka 'struct node') with an expression of incompatible type 'node *' (aka 'struct node *'); dereference with *
        node word = hashtable[i];
             ^      ~~~~~~~~~~~~
                    *
dictionary.c:97:10: error: initializing 'node' (aka 'struct node') with an expression of incompatible type 'node *' (aka 'struct node *'); dereference with *
    node cword = hashtable[hash(word)];
         ^       ~~~~~~~~~~~~~~~~~~~~~
                 *
4 errors generated.
Makefile:2: recipe for target 'speller' failed
make: *** [speller] Error 1

Code:

// Implements a dictionary's functionality

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#include "dictionary.h"

// Represents number of buckets in a hash table
#define N 26

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

// Represents a hash table
node *hashtable[N];

// Hashes word to a number between 0 and 25, inclusive, based on its first letter
unsigned int hash(const char *word)
{
    return tolower(word[0]) - 'a';
}

// Adds word to list
void append(const char *word, node list)
{
    node nNode;
    nNode.word = word;
    nNode.next = &list;
    &list.next = *nNode;
}

// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
    // Initialize hash table
    for (int i = 0; i < N; i++)
    {
        hashtable[i] = NULL;
    }

    // Open dictionary
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        unload();
        return false;
    }

    // Buffer for a word
    char word[LENGTH + 1];

    // Insert words into hash table
    while (fscanf(file, "%s", word) != EOF)
    {
        append(word, *hashtable[hash(word)]);
    }

    // Close dictionary
    fclose(file);

    // Indicate success
    return true;
}

// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
    int count = 0;
    if (hashtable[0] == NULL)
    {
        return 0;
    }
    int words = 0;
    for (int i = 0; i < N; i++)
    {

        node word = hashtable[i];
        while (word.next != NULL)
        {
            count++;
            *word = word.next;
        }
    }
    return count;
}

// Returns true if word is in dictionary else false
bool check(const char *word)
{
    node cword = hashtable[hash(word)];
    while (cword.next != NULL)
    {
        if (cword.word == word)
        {
            return true;
        }
        *cword = cword.next;
    }
    return false;
}

// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
    free(hashtable);
    return true;
}
2
  • 2
    Could make some swag guesses, but to meaningfully answer, we need to see some code - at minimum, all the declarations of all the vars involved and all of the lines of code identified by the errors. Please edit your question and insert the needed code. But my guess on the first error is that you're trying to copy the current word using the = assignment operator when it should be done with strcpy().
    – Cliff B
    Commented May 20, 2019 at 1:30
  • Looks like there are a few node type variables that maybe should be node* instead (pointer to node), so the actual data is on heap, not stack (requires malloc or equivalent). There's the -> operator which is quite useful, A->B is (*A).B, combining dereferencing a pointer with accessing a struct member.
    – Blauelf
    Commented May 20, 2019 at 15:56

1 Answer 1

2

I'll pick one.

// Adds word to list
void append(const char *word, node *list)

What is this meant to do? I guess you pass a word and the pointer to the list head, and expect a new node to be added to the list. But how would you handle an empty list (which is usually represented by NULL)? For that, the usual solution is to either return the new list head (and rely on the calling code to assign), or pass a pointer to pointer to node (something like node **head_ptr). You could find some info in the shorts (you've watched them, right?), or if you like text, I found the pdfs from http://cslibrary.stanford.edu/103/ and related quite interesting.

Let's continue.

{
    node *nNode;

So you declare a pointer to node. But you don't assign any value. malloc would probably help here.

    strcpy(nNode->word, word);

And crash, because nNode's value is undefined (could be anything) and you dereference it. Poor Binky.

    nNode->next = &list;
    &list->next = nNode;
}

Since nNode->next and list are both node*, the & makes no sense. Especially it does not make any sense on the left side (how would you assign to a memory address?).

So you actually tried to "prepend" a node in your "append" function? Probably a question of perspective.

But then,

append(word, *hashtable[hash(word)]);

would call that with a node, not node*. Why dereference it there?

2
  • I did that and ran it, but it's still the same error. (P.S. I did that yesterday but didn't have time to edit the code here)
    – fwoosh
    Commented May 21, 2019 at 23:47
  • I edited the code and now it says MISSPELLED WORDS Segmentation fault
    – fwoosh
    Commented May 22, 2019 at 0:17

You must log in to answer this question.

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