I'm still trying to cope up with Pset5 So what I have: program shows 14 from 17 words in text as misspelled and is ended with
*** Error in `./speller': free(): corrupted unsorted chunks: 0x0000000001329010 ***
Aborted
GDB alerts me showing some strange value for "word" It is not good, right?
while (fscanf(fp, "%s", word) !=EOF) //scan dictionary word by word till EOF
(gdb) print word
$2 = "\177ELF\002\001\001\000\000\000\000\000\000\000\000\000\002\000>\000\001\000\000\000\000\b@\000\000\000\000\000@\000\000\000\000\000\000\000h?\000\000\000"
(gdb)
And Valgrind does not make me happy with Illegal read/write errors like this
==17339== Invalid write of size 8
==17339== at 0x4E9517D: _IO_acquire_lock_clear_flags2_fct (libioP.h:915)
==17339== by 0x4E9517D: __isoc99_fscanf (isoc99_fscanf.c:30)
==17339== by 0x401335: load (dictionary.c:88)
==17339== by 0x4009CD: main (speller.c:45)
==17339== Address 0x51fc128 is 232 bytes inside a block of size 568 free'd
==17339== at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17339== by 0x4EA4A24: fclose@@GLIBC_2.2.5 (iofclose.c:85)
==17339== by 0x401407: load (dictionary.c:118)
==17339== by 0x4009CD: main (speller.c:45)
Also Valgrind shows that my dictionary has only 1 word (my small dictionary has 17 words, and text has 15 words, where 2 are misspelled)
WORDS MISSPELLED: 14
WORDS IN DICTIONARY: 1
WORDS IN TEXT: 14
TIME IN load: 0.04
TIME IN check: 0.00
TIME IN size: 0.00
TIME IN unload: 0.01
TIME IN TOTAL: 0.05
==17339==
==17339== HEAP SUMMARY:
==17339== in use at exit: 0 bytes in 0 blocks
==17339== total heap usage: 3 allocs, 3 frees, 1,192 bytes allocated
==17339==
==17339== All heap blocks were freed -- no leaks are possible
==17339==
==17339== For counts of detected and suppressed errors, rerun with: -v
==17339== ERROR SUMMARY: 80 errors from 72 contexts (suppressed: 0 from 0)
I suppose that problem is in Load. Fscanf? strcpy? I'm confused. Here is my code and sorry for the long post and thanks for your time!
#include <stdbool.h>
#include "dictionary.h"
int words = 0; //words loaded from the dictionary
// define a node type
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
}
node;
// define a hashtable
node* hashtable[HASHTABLE_SIZE];
// hashing function from https://www.reddit.com/r/cs50/comments/1x6vc8/pset6_trie_vs_hashtable/cf9nlkn/
int hash_it(char* needs_hashing)
{
unsigned int hash = 0;
for (int i=0, n=strlen(needs_hashing); i<n; i++)
hash = (hash << 2) ^ needs_hashing[i];
return hash % HASHTABLE_SIZE;
}
/**
* Returns true if word is in dictionary else false.
*/
bool check(const char* word)
{
int len = strlen(word);
char buffer[len + 1];
buffer[len] = '\0';
for (int i = 0; i < len; i++)
{
buffer[i] = word[i];
}
int h = hash_it(buffer);
node *cursor = hashtable[h];
while (cursor !=NULL)
{
if (strcasecmp (cursor->word, buffer) == 0)
{
return true;
}
else
{
cursor = cursor->next;
}
}
return false;
}
/**
* Loads dictionary into memory. Returns true if successful else false.
*/
bool load(const char* dictionary)
{
//initialise hash table
for (int i = 0; i < HASHTABLE_SIZE; i++)
{
hashtable[i] = NULL;
}
//open dictionary
FILE* fp = fopen(dictionary, "r");
if (fp == NULL)
{
printf("Could not open dictionary.\n");
unload();
return false;
}
char word[LENGTH + 1];
while (fscanf(fp, "%s", word) !=EOF) //scan dictionary word by word till EOF
{
node *new_node = malloc(sizeof(node)); //make a new node
if (new_node == NULL)
{
fclose(fp);
return false;
}
else
{
strcpy (new_node->word, word); //copy word from dictionary to a new node
words++;
}
//hashing new_node->word
int h = hash_it(new_node->word);
node* head = hashtable[h];
//insert into a linked list
if (head == NULL) // if bucket is empty, insert the first node
{
hashtable[h] = new_node;
}
else
{
new_node->next = hashtable[h]; //if not- make new links
hashtable[h] = new_node;
}
fclose(fp); // close dictionary
}
return true;
}
/**
* Returns number of words in dictionary if loaded else 0 if not yet loaded.
*/
unsigned int size(void)
{
if (words >= 1)
{
return words;
}
else
{
return 0;
}
}
/**
* Unloads dictionary from memory. Returns true if successful else false.
*/
bool unload(void)
{
for (int i = 0; i < HASHTABLE_SIZE; i++)
{
node *cursor = hashtable[i];
while (cursor !=NULL)
{
node* temp = cursor;
cursor = cursor->next;
free(temp);
}
}
return true;
}