0

From the posts that I have checked, it seems that my code has an error coming from load because when checking with large dictionary, the only output I get is MISSPELLED WORDS and the program has to be stopped via Ctrl+C.When I ran using the small dictionary, I suspect there's an error related to unload because of the error message: "Error in `./speller': double free or corruption" with no output statistic. But I am not sure how to correct either errors as I seem to be doing things correctly?

    typedef struct node
    {
       char word[LENGTH + 1];
       struct node* next;
    }
    node;

   //creates array of nodes of size HASHTABLE_SIZE
   node* hashtable[HASHTABLE_SIZE];


   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;
   }


   int word_count = 0;

   bool loaded = false;



   bool check(const char *word)
   {

       int length = strlen(word); 
       char word_cpy[length + 1];

   for (int j = 0; j < length; j++)
   {
       word_cpy[j] = tolower(word[j]);
   }

   word_cpy[length] = '\0'; //add null terminator to end of char array

   int h = hash_it(word_cpy);

   node *cursor = hashtable[h];

   while(cursor != NULL)
  {
      if (strcasecmp(cursor -> word, word) == 0)
      {
         return true;
      }
     else
     {
         cursor = cursor -> next;
     }
  }
  return false;
}


bool load(const char *dictionary)
{

for (int i = 0; i < HASHTABLE_SIZE; i++)
{
    hashtable[i] = NULL;
}
//open dictionary
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
    return false;
}

//malloc a node pointer
//node *node1 = malloc(sizeof(node));

char word[LENGTH+1];


while (fscanf(dict, "%s", word) != EOF)
{
    word_count++;
    node *node1 = malloc(sizeof(node));


    if (node1 == NULL)
    {
        unload(); //unload dictionary
        return false; //quit speller
    }

    strcpy(node1 -> word, word);
    int h = hash_it(node1 -> word);

    if (node1 == NULL) //Is this part correct?
    {
        hashtable[h] = node1; 
    }
    else 
    {
        node1 -> next = hashtable[h]; 
        hashtable[h] = node1; 
    }
}
fclose(dict);
loaded = true;
return true;
}


unsigned int size(void)
{

if (loaded)
{
    return word_count;
    printf("word count:%i", word_count);
}
else 
{
    return 0;
}
}


bool unload(void)
{
// TODO
for (int k = 0; k < HASHTABLE_SIZE; k++)
{
    node *cursor = hashtable[k];
    while (cursor != NULL)
    {
        node *temp = cursor;
        cursor = cursor -> next;
        free(temp);
    }

}
loaded = false;
return true;
}
1
  • EDIT: I have pasted the new code and the question I have now is whether the 2nd "if (node1 == NULL)" is correct because it doesn't make sense to me since the 1st "if(node1 ==NULL)" checks whether malloc has succeeded. Can anyone enlighten me on this? – aman0016 Oct 13 '17 at 11:21
0
node *node1 = malloc(sizeof(node));

would need to go within the loop (at least the malloc part). Otherwise, you'd work with one node only, and eventually have this node placed in many hashtable entries, with a bit of luck even its next pointer pointing to itself, making check run infinite (likely for a large dict), or the next pointer is NULL, then your unload would double-free it (likely for a small dict). Single mistake explains both kinds of failure.

BTW, the if-else in size adds exactly nothing, unless you find a way to have word_count be less than 0. The

    if (hashtable[h] == NULL) //if bucket is empty
    {
        hashtable[h] = node1; //inserts 1st node
        node1 -> next = NULL;
    }
    else 

also adds nothing (if hashtable[h] is NULL, you can swap those two lines and replace that second NULL with hashtable[h] and suddenly have the code of the else path)

3
  • Hi, I tried with your suggestions and the code is working. But I don't see how it should work and yet it passes check50. I have edited in the post and hope you can take a look to see if there's any error made that I didn't realize. – aman0016 Oct 13 '17 at 11:22
  • Use just node1 -> next = hashtable[h]; hashtable[h] = node1; without any if-else. – Blauelf Oct 13 '17 at 13:11
  • It worked! Thank you. – aman0016 Oct 13 '17 at 15:27

You must log in to answer this question.

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