0

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;

    }
2

It seems to me that because your hash function is not case-insensitive all of the words with capital letters get hashed to a different location (h) before you get to use strcasecmp.

0

I coped up with most of the problems by getting out fclose(fp); from while loop in load. So don't be like me, be attentive :)

So the only problem - program is not case insensitive despite of strcasecmp, which should be

1

You must log in to answer this question.

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