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;
}
node
type variables that maybe should benode*
instead (pointer tonode
), so the actual data is on heap, not stack (requiresmalloc
or equivalent). There's the->
operator which is quite useful,A->B
is(*A).B
, combining dereferencing a pointer with accessing a struct member.