Skip to main content
deleted 4114 characters in body
Source Link

My final code looks like this:

// Implements a dictionary's functionality #include <ctype.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "dictionary.h" // Represents a node in a hash table typedef struct node { char word[LENGTH + 1]; struct node *next; } node; // TODO: Choose number of buckets in hash table (Additional comment: each bucket is a linked list) const unsigned int N = 4500; // Hash table node *table[N]; int words_amount = 0; bool is_loaded = false; // Returns true if word is in dictionary, else false bool check(const char *word) { // TODO int bucket_indx = 0; char *lowercase_word = malloc((sizeof(char)) * (strlen(word) + 1)); strcpy(lowercase_word, word); for (int i = 0; lowercase_word[i] != '\0'; i++) { lowercase_word[i] = tolower(lowercase_word[i]); } bucket_indx = hash(lowercase_word); node *cursor = table[bucket_indx]; while (cursor != NULL) { if (strcmp(cursor->word, lowercase_word) == 0) { free(lowercase_word); return true; } else { cursor = cursor->next; } } free(lowercase_word); return false; } // Hashes word to a number unsigned int hash(const char *word) { // TODO: Improve this hash function unsigned int hash_addition = 0; char *lowercase_word = malloc(strlen(word) + 1); if (lowercase_word == NULL) { return false; } strcpy(lowercase_word, word); for (int i = 0; lowercase_word[i] != '\0'; i++) { lowercase_word[i] = tolower(lowercase_word[i]); } int length = strlen(lowercase_word); for (int i = 0; i < length; i++) { hash_addition = hash_addition + (lowercase_word[length - i] * lowercase_word[i]); } free(lowercase_word); return hash_addition % N; } // Loads dictionary into memory, returning true if successful, else false bool load(const char *dictionary) { // TODO char buffer[LENGTH + 1]; node *n = NULL; // Open the dictionary file FILE *source = fopen(dictionary, "r"); if (source == NULL) { printf("Error: Could not open file.\n"); return false; } // Copy each word read from the file to a new node else { while (fscanf(source, "%s", buffer) != EOF) { n = malloc(sizeof(node)); { if (n == NULL) { fclose(source); return false; } } // Convert word in buffer to lowercase, character by character for (int i = 0; buffer[i] != '\0'; i++) { buffer[i] = tolower(buffer[i]); } strcpy(n->word, buffer); int index = hash(buffer); n->next = table[index]; table[index] = n; words_amount++; } is_loaded = true; fclose(source); return true; } } // Returns number of words in dictionary if loaded, else 0 if not yet loaded unsigned int size(void) { // TODO if (!is_loaded) { return 0; } else { return words_amount; } } // Unloads dictionary from memory, returning true if successful, else false bool unload(void) { // TODO int i = 0; node *cursor = NULL; node *tmp = NULL; for (i = 0; i < N; i++) { cursor = table[i]; while (cursor != NULL) { tmp = cursor; cursor = cursor->next; free(tmp); } words_amount = 0; } // At this point cursor should be NULL anyway, so checking if i= N is enough to find out if all // the nodes are freed if (i == N && size() == 0) { return true; } else { return false; } } 

Big thanks to @UpAndAdam and @DinoCoderSaurus that took the time to help me solve the issue!

My final code looks like this:

// Implements a dictionary's functionality #include <ctype.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "dictionary.h" // Represents a node in a hash table typedef struct node { char word[LENGTH + 1]; struct node *next; } node; // TODO: Choose number of buckets in hash table (Additional comment: each bucket is a linked list) const unsigned int N = 4500; // Hash table node *table[N]; int words_amount = 0; bool is_loaded = false; // Returns true if word is in dictionary, else false bool check(const char *word) { // TODO int bucket_indx = 0; char *lowercase_word = malloc((sizeof(char)) * (strlen(word) + 1)); strcpy(lowercase_word, word); for (int i = 0; lowercase_word[i] != '\0'; i++) { lowercase_word[i] = tolower(lowercase_word[i]); } bucket_indx = hash(lowercase_word); node *cursor = table[bucket_indx]; while (cursor != NULL) { if (strcmp(cursor->word, lowercase_word) == 0) { free(lowercase_word); return true; } else { cursor = cursor->next; } } free(lowercase_word); return false; } // Hashes word to a number unsigned int hash(const char *word) { // TODO: Improve this hash function unsigned int hash_addition = 0; char *lowercase_word = malloc(strlen(word) + 1); if (lowercase_word == NULL) { return false; } strcpy(lowercase_word, word); for (int i = 0; lowercase_word[i] != '\0'; i++) { lowercase_word[i] = tolower(lowercase_word[i]); } int length = strlen(lowercase_word); for (int i = 0; i < length; i++) { hash_addition = hash_addition + (lowercase_word[length - i] * lowercase_word[i]); } free(lowercase_word); return hash_addition % N; } // Loads dictionary into memory, returning true if successful, else false bool load(const char *dictionary) { // TODO char buffer[LENGTH + 1]; node *n = NULL; // Open the dictionary file FILE *source = fopen(dictionary, "r"); if (source == NULL) { printf("Error: Could not open file.\n"); return false; } // Copy each word read from the file to a new node else { while (fscanf(source, "%s", buffer) != EOF) { n = malloc(sizeof(node)); { if (n == NULL) { fclose(source); return false; } } // Convert word in buffer to lowercase, character by character for (int i = 0; buffer[i] != '\0'; i++) { buffer[i] = tolower(buffer[i]); } strcpy(n->word, buffer); int index = hash(buffer); n->next = table[index]; table[index] = n; words_amount++; } is_loaded = true; fclose(source); return true; } } // Returns number of words in dictionary if loaded, else 0 if not yet loaded unsigned int size(void) { // TODO if (!is_loaded) { return 0; } else { return words_amount; } } // Unloads dictionary from memory, returning true if successful, else false bool unload(void) { // TODO int i = 0; node *cursor = NULL; node *tmp = NULL; for (i = 0; i < N; i++) { cursor = table[i]; while (cursor != NULL) { tmp = cursor; cursor = cursor->next; free(tmp); } words_amount = 0; } // At this point cursor should be NULL anyway, so checking if i= N is enough to find out if all // the nodes are freed if (i == N && size() == 0) { return true; } else { return false; } } 

Big thanks to @UpAndAdam and @DinoCoderSaurus that took the time to help me solve the issue!

Big thanks to @UpAndAdam and @DinoCoderSaurus that took the time to help me solve the issue!

Source Link

Well, it turned out that I had made changes in the other 2 files unintentionally (dictionary.h or speller.c).

I incorporated most of the suggestions UpAndAdam posted, but ultimately the solution was simpler and DinoCoderSaurus really helped me troubleshoot the issue. I downloaded speller.zip again and pasted the code in my dictionary.c file and the issue is resolved (check50 now says my code compiles and passes all the tests).

enter image description here

I have to admit I feel quite stupid, as I have been changing things in my code for two days now and I hadn't tried the easiest solution, which was just checking if the other two files of the program were intact. It seems that I had changed something in there while reading the code without realizing.

My final code looks like this:

// Implements a dictionary's functionality #include <ctype.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "dictionary.h" // Represents a node in a hash table typedef struct node { char word[LENGTH + 1]; struct node *next; } node; // TODO: Choose number of buckets in hash table (Additional comment: each bucket is a linked list) const unsigned int N = 4500; // Hash table node *table[N]; int words_amount = 0; bool is_loaded = false; // Returns true if word is in dictionary, else false bool check(const char *word) { // TODO int bucket_indx = 0; char *lowercase_word = malloc((sizeof(char)) * (strlen(word) + 1)); strcpy(lowercase_word, word); for (int i = 0; lowercase_word[i] != '\0'; i++) { lowercase_word[i] = tolower(lowercase_word[i]); } bucket_indx = hash(lowercase_word); node *cursor = table[bucket_indx]; while (cursor != NULL) { if (strcmp(cursor->word, lowercase_word) == 0) { free(lowercase_word); return true; } else { cursor = cursor->next; } } free(lowercase_word); return false; } // Hashes word to a number unsigned int hash(const char *word) { // TODO: Improve this hash function unsigned int hash_addition = 0; char *lowercase_word = malloc(strlen(word) + 1); if (lowercase_word == NULL) { return false; } strcpy(lowercase_word, word); for (int i = 0; lowercase_word[i] != '\0'; i++) { lowercase_word[i] = tolower(lowercase_word[i]); } int length = strlen(lowercase_word); for (int i = 0; i < length; i++) { hash_addition = hash_addition + (lowercase_word[length - i] * lowercase_word[i]); } free(lowercase_word); return hash_addition % N; } // Loads dictionary into memory, returning true if successful, else false bool load(const char *dictionary) { // TODO char buffer[LENGTH + 1]; node *n = NULL; // Open the dictionary file FILE *source = fopen(dictionary, "r"); if (source == NULL) { printf("Error: Could not open file.\n"); return false; } // Copy each word read from the file to a new node else { while (fscanf(source, "%s", buffer) != EOF) { n = malloc(sizeof(node)); { if (n == NULL) { fclose(source); return false; } } // Convert word in buffer to lowercase, character by character for (int i = 0; buffer[i] != '\0'; i++) { buffer[i] = tolower(buffer[i]); } strcpy(n->word, buffer); int index = hash(buffer); n->next = table[index]; table[index] = n; words_amount++; } is_loaded = true; fclose(source); return true; } } // Returns number of words in dictionary if loaded, else 0 if not yet loaded unsigned int size(void) { // TODO if (!is_loaded) { return 0; } else { return words_amount; } } // Unloads dictionary from memory, returning true if successful, else false bool unload(void) { // TODO int i = 0; node *cursor = NULL; node *tmp = NULL; for (i = 0; i < N; i++) { cursor = table[i]; while (cursor != NULL) { tmp = cursor; cursor = cursor->next; free(tmp); } words_amount = 0; } // At this point cursor should be NULL anyway, so checking if i= N is enough to find out if all // the nodes are freed if (i == N && size() == 0) { return true; } else { return false; } } 

Big thanks to @UpAndAdam and @DinoCoderSaurus that took the time to help me solve the issue!