I finished writing my code for speller. It compiles fine but the only output being printed is "Misspelled words". The words misspelled , words in text, words in dictionary does not get printed. I'm assuming its because the program crashes before then? Here is my code. If only I knew in which function or area my problem lies I might be able to fix it. Also, my hash function is to base hash indexes base on the first two letters of the word.
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dictionary.h"
int dsize = 0;
// 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
const unsigned int N = 676;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
// hash word
int hashnumber = hash(word);
node *cursor = table[hashnumber];
// traversing linked list at that hash number
while(cursor != NULL)
{
if((strcasecmp(cursor->word, word) == 0))
{
return true;
}
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
int hash;
// TODO: Improve this hash function
for( int i = 97; i < 123; i ++)
{
hash = (i - 97) * 26;
// check asciivalue both uppercase and lowercase for first letter
if(word[0] == (char)i || word[0] == (char)(i - 32) )
{
for ( int j = 97; j < 122; j++)
{
// check asciivalue both uppercase and lowercase for second letter
if(word[1] == (char)j || word[1] == (char)(j - 32))
{
hash = hash + (j - 97);
}
}
}
}
return hash;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
for( int i = 0; i < N; i++)
{
table[i] = NULL;
}
FILE *input = fopen(dictionary, "r");
if (dictionary== NULL)
{
return false;
}
node *temp;
char word[LENGTH + 1];
while((fscanf(input, "%s", word)) != EOF)
{
temp = malloc(sizeof(node));
if(temp == NULL)
{
return false;
}
strcpy(temp->word, word);
int hashnumber = hash(word);
if (table[hashnumber] == NULL)
{
table[hashnumber] = temp;
}
else
{
temp->next = table[hashnumber];
table[hashnumber] = temp;
}
dsize++;
}
fclose(input);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
return dsize;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
node *temp;
node *cursor;
for ( int i = 0; i < N; i++ )
{
cursor = table[i];
while(table[i] != NULL)
{
temp = cursor;
cursor = cursor->next;
free(temp);
}
if(cursor == NULL && i == (N - 1))
{
return true;
}
}
return false;
}
Related
When i use valgrind i get: Conditional jump or move depends on uninitialised value(s) on line 37.
Line 37 is where the while loop starts, in the function "check".
I dont know what causes this problem, what it means or how to fix it.
Besides this there are no other problems.
This program is designed to take a dictionary and put it into a hash-table. then a text can be reviewed with the "check" function.
// Implements a dictionary's functionality
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <cs50.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;
int counter = 0;
// TODO: Choose number of buckets in hash table
const unsigned int N = 676;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
int hash_value = hash(word);
node *cursor = table[hash_value];
while(cursor != NULL)
{
if(strcasecmp(cursor->word,word) == 0)
{
return true;
}
cursor = cursor->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
int hash_0 = 0;
int hash_1 = 0;
for (int i = 65; i < 91; i++)
{
if (word[0] == i || word[0] == (i + 32))
{
hash_0 = (i - 65);
}
if (word[1] == i || word[1] == (i + 32))
{
hash_1 = (i - 65);
}
}
return ((hash_0 * 26) + hash_1);
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// opens the dictionary file
bool outcome = true;
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
outcome = false;
fclose(dict);
}
// read strings from file
char woord[LENGTH];
while (fscanf(dict, "%s", woord) != EOF)
// put string in node
{
node *pointer = malloc(sizeof(node));
counter++;
if (pointer == NULL)
{
outcome = false;
fclose(dict);
break;
}
strcpy(pointer -> word, woord);
// use the hash function
int hash_value = hash(pointer -> word);
// insert node into Hash Table
if (table[hash_value] == NULL)
{
table[hash_value] = pointer;
}
else
{
pointer -> next = table[hash_value];
table[hash_value] = pointer;
}
}
fclose(dict);
return outcome;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
return counter;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
bool outcome = true;
for (int i = 0; i < N; i++)
{
node *cursor = table[i];
node *destroyer = table[i];
while(cursor != NULL)
{
cursor = cursor -> next;
free(destroyer);
destroyer = cursor;
}
}
return outcome;
}
I am working on Pset5 Speller. I made hashing function using the concept of binary numbers of base 26. So single alphabet words are stored in index 1-26, words containing apostrophes are stored in index 0 and the remaining are hashed using the first two alphabets. I tried to debug the code and run Valgrind on it still was unable to find the reason for failing of Substring tests any suggestions
// Implements a dictionary's functionality
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <cs50.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = (26 * 26) + 26 + 1 ;
// Hash table
node *table[N];
int numberofwords = 0;
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
int index = hash(word);
node *checker;
checker = table[index];
while (checker != NULL)
{
int comp = strcasecmp(word, checker->word);
if (comp == 0)
{
return true;
}
else
{
checker = checker->next;
}
}
// TODO
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
int value = 0;
int length = strlen(word);
for (int i = 0; i < length; i++)
{
char c = word[i];
if (c == '\'')
{
value = 0;
return value;
}
}
if (length == 1)
{
value = tolower(word[0]) - 'a' + 1;
return value;
}
else
{
value = (26 * (tolower(word[1]) - 'a' + 1)) + (tolower(word[0]) - 'a' + 1);
return value;
}
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
//open dictionary and loop till EOF
char buffer[LENGTH + 1];
FILE *temp = fopen(dictionary, "r");
if (temp == NULL)
{
return false;
}
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
while (fscanf(temp, "%s", buffer) != EOF)
{
node *temp_node = malloc(sizeof(node));
if (temp_node == NULL)
{
return false;
}
strcpy(temp_node->word, buffer);
temp_node->next = NULL;
//hash the word
int locate = hash(buffer);
if (table[locate] == NULL)
{
table[locate] = temp_node;
}
else
{
temp_node->next = table[locate];
table[locate] = temp_node -> next;
}
numberofwords++;
}
fclose(temp);
// TODO
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
return numberofwords;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
for (int i = 0; i < N; i++)
{
node *start = table[i];
node *freeer = start;
node *remember = start;
while (remember != NULL)
{
remember = remember->next;
free(freeer);
freeer = remember;
}
}
// TODO
return true;
}
here is the link to errors
https://submit.cs50.io/check50/ef7901d85e821af117b76bf7a2f43f44f38e3301
This looks like a problem in load:
temp_node->next = table[locate];
table[locate] = temp_node -> next;
It looks circular, they are pointing to each other.
Try debugging with the small dictionary and a text file that contains the 5 words in ACTUAL OUTPUT pane plus the word cat.
check50 did not check for memory errors because of the failed test ("can't check until a frown turns upside down")
currently doing the speller problem of cs50 pset5.
I'm having a trouble with forming the hash table and i think it causes a segmentation fault later on when i try to run a function that searches the table.
this is the function that creates the hash table:
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r"); //opens dictionary file
if (dict == NULL) // if cant be opened loading failed
{
return false;
}
char w[LENGTH + 1]; //buffer (length is the maximum character number
int i = 0; //index within word
while(fscanf(dict, "%s", w) != EOF) // scanning the dictionary for words
{
int x = hash(w); //getting the number of the linked list within the table
node *n = malloc(sizeof(node)); //allocating memory for a new node
if (n == NULL)
{
return false;
}
for (int j = 0; j < strlen(w) + 1; j++) // documenting the word within the new node
{
n->word[i] = w[j];
}
n->next = table[x];
table[x] = n; //new node is the beginning of the linked list
dicsize++;
}
fclose(dict);
return true;
}
my main question is whether my code for forming the table is correct and if not then why
thank you in advance
and this is the entire code:
// Implements a dictionary's functionality
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "dictionary.h"
// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// Number of buckets in hash table
const unsigned int N = 26;
int dicsize = 0;
// Hash table
node *table[N];
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
int x = hash(word);
node *cur = table[x];
while(table[x] != NULL)
{
if(strcasecmp(word, cur->word) == 0)
{
return true;
}
if(cur == NULL)
{
return false;
}
cur = cur->next;
}
return false;
}
// Hashes word to a number
unsigned int hash(const char *word)
{
char temp = tolower(word[0]);
int place = (temp - 97);
return place;
}
// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
FILE *dict = fopen(dictionary, "r"); //opens dictionary file
if (dict == NULL) // if cant be opened loading failed
{
return false;
}
char w[LENGTH + 1]; //buffer
int i = 0; //index within word
while(fscanf(dict, "%s", w) != EOF) // scanning the dictionary for words
{
int x = hash(w); //getting the number of the linked list within the table
node *n = malloc(sizeof(node)); //allocating memory for a new node
if (n == NULL)
{
return false;
}
for (int j = 0; j < strlen(w) + 1; j++) // documenting the word within the new node
{
n->word[i] = w[j];
}
n->next = table[x];
table[x] = n; //new node is the beginning of the linked list
dicsize++;
}
fclose(dict);
return true;
}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
printf("%i", dicsize);
return dicsize;
}
// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
return false;
}
The likely culprit is
for (int j = 0; j < strlen(w) + 1; j++) // documenting the word within the new node
{
n->word[i] = w[j];
}
As i is not changing inside the loop, instead of copying the string it will dump all the chars into one. The other index should also be j. (as in n->word[j] = w[j];)
It would be better to do this as strcpy anyway.
I am working through the CS50 Speller problem and facing a problem that when running the program it returns an error of "Could not unload dictionaries/large."
I have looked at other people's solutions and can't for the life of me identify what is going wrong in my program. I am thinking it is in the has function, but have seen this has function in other people's working programs?
Any help would be greatly appreciated.
// Implements a dictionary's functionality
#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;
// Number of words in dictionary
int word_count = 0;
// Number of buckets in hash table
const unsigned int N = 26;
// Hash table
node *table[N];
// Returns true if word is in dictionary else false
bool check(const char *word)
{
unsigned int n = hash(word);
node *cursor = table[n];
while (cursor != NULL)
{
if (strcasecmp(word, cursor -> word) == 0)
{
return true;
}
cursor = cursor -> next;
}
return false;
}
// Hashes word to a number
// Function credit to delipity(staff) on CS50 reddit page
unsigned int hash(const char *word)
{
unsigned int hash_value = 0;
for (int i = 0, n = strlen(word); i < n; i++)
{
hash_value = (hash_value << 2) ^ word[i];
}
return hash_value % N; //N is size of hashtable
}
// Loads dictionary into memory, returning true if successful else false
bool load(const char *dictionary)
{
// Open dictionary and check for memory issue
// Open dictionary file and create word array
FILE *dict = fopen(dictionary, "r");
char word[LENGTH + 1];
// Check for memory issue with dict
if(dict == NULL)
{
printf("Dictionary is null\n");
unload();
return false;
}
// Read string 1 word at a time
while (fscanf(dict, "%s", word) != EOF)
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return false;
}
strcpy(n -> word, word);
word_count++;
// Index word using hash function
int dict_index = hash(word);
// Insert into hash table if already empty
if (table[dict_index] == NULL)
{
n -> next = NULL;
}
// Insert work as new node if not empyty
else
{
n -> next = table[dict_index];
}
table[dict_index] = n;
}
// Close dictionary file
fclose(dict);
// Indicate success
return true;
}
// Returns number of words in dictionary if loaded else 0 if not yet loaded
unsigned int size(void)
{
return word_count;
return 0;
}
// Unloads dictionary from memory, returning true if successful else false
bool unload(void)
{
for (int i = 0; i < N; i++)
{
node *cursor = table[i];
node *tmp = cursor;
while (cursor != NULL)
{
cursor = cursor -> next;
free(tmp);
tmp = cursor;
}
}
return false;
}
bool unload(void)
{
for (int i = 0; i < N; i++)
{
node *cursor = table[i];
while (cursor)
{
node *temp = cursor;
cursor = cursor->next;
free(temp);
}
}
return true;
}
Try this instead for the unload function
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dictionary.h"
#define HASH_SIZE 5
// prototype
int hash(char *word);
// counter
int counter;
// node
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
} node;
// hash table
struct node *hashtable[HASH_SIZE];
/*
* Returns true if word is in dictionary else false.
*/
bool
check(const char *word)
{
//make a writable word (palabra)
int len = strlen(word);
char palabra[len + 1];
//int i;
// make la palabra all lowercase letters
for ( int i = 0; i < len; i++)
{
if (isalpha(palabra[i]) || palabra[i] == '\'')
palabra[i] = tolower(word[i]);
}
//palabra[i] = (char) "\0";
// hash the word
int value = hash(palabra);
// let's look at the first node in the bucket
struct node *n;
if (hashtable[value] == NULL)
return false;
else
n = hashtable[value];
// iterate through the bucket to see if the word is there
while (strcmp(palabra, n->word) != 0 && n->next != NULL)
{
n = n->next;
}
// if the word is found, print true, else false
if ( strcmp(palabra, n->word) ==0 )
return true;
else
return false;
}
/*
* Loads dictionary into memory. Returns true if successful else false.
*/
bool
load(const char *dictionary)
{
// open the dictionary
FILE *dict = fopen(dictionary, "r");
if(dict == NULL)
{
printf("Could not open %s.\n", dictionary);
return false;
}
// set all values in the hash table to null
for(int i = 0; i < HASH_SIZE; i++)
{
hashtable[i] = NULL;
}
// set the counter to 0
counter = 0;
// iterate through the words in the dictionary
while (!feof(dict))
{
//declare a node
node *n = malloc( sizeof(node) );
// copy the word into the node
fscanf(dict, "%s", n->word);
// hash the word, baby!
int hash_value = hash(n->word);
// start saving addresses to the hashtable
n->next = hashtable[hash_value];
hashtable[hash_value] = n;
// that's one more!
counter++;
}
// testing
printf("Starting the test.\n");
for ( int i = 0; i < HASH_SIZE; i++)
{
struct node *q = hashtable[i];
while (q != NULL)
{
printf("%s\n", q->word);
q = q->next;
}
}
printf("Ending the test.\n");
fclose(dict);
return true;
}
/*
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int
size(void)
{
return counter;
}
/*
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool
unload(void)
{
// TODO
return false;
}
/*
* Returns a hash value for a word.
*/
int
hash(char *word)
{
// hash value and length of word
int value = 0;
int len = strlen(word);
// iterate through letters, adding ASCII values
for(int i = 0; i < len; i++)
{
int letter = (int) word[i];
value += letter;
}
// make sure the value is less than 100 & return
value = value%HASH_SIZE;
return value;
}
When I run my code, I receive this error message:
In file included from /usr/include/ctype.h:28:0,
from speller.c:10:
/usr/include/bits/types.h:31:1: error: expected '=', ',', ';', 'asm' or 'attribute' before 'typedef'
Does this mean that I have somehow managed to alter the ctype.h library? If so, how do I fix it?
Aha! Gordon, you solved it! I found some stray characters typed just above the #include that were causing the problem. Thanks!