0

My check function is counting the right amount of words in dictionary and text, but it outputs words that are not misspelled.

Here are all the functions of the problem, the arrays are used to locate the word. And I created a new table (cambio).

// Implements a dictionary's functionality

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.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 = 1;

// Hash table
node *table[N];

// New table
const unsigned int NUEVO = 26;
node *cambio[26];

// Arrays for hash function
char letras[26] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
int numeros[26] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};


// Check function variables 
node *seguido;

// Amount of words in dictionary
int palabras = 0;
int *cantidad_palabras = &palabras;

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    int position = hash(word);
    node *comparador = cambio[position];
    
    for (; comparador->next != NULL; comparador = comparador->next)
    {
        if (strcasecmp(comparador->word, word) == 0)
        {
            return true;
        }
        else
        {
            continue;
        }
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    int index = 0;
    char letra = tolower(word[0]);
   
   for (int i = 0; i < 25; i++)
   {
       if (letra == letras[i])
       {
           index = numeros[i];
           return index;
       }
       else
       {
           continue;
       }
   }
   return 1;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    char palabra[LENGTH + 1];
    FILE *diccionario = fopen(dictionary, "r");
    
    if (diccionario == NULL)
    {
        return false;
    }
    
    while (fscanf(diccionario, "%s", palabra) != EOF)
    {
        node *nodo = malloc(sizeof(node));
        strcpy(nodo->word, palabra);
        
        int position = hash(palabra);
        
         if (cambio[position] != NULL)
        {
            node *tmp = cambio[position];
            cambio[position] = nodo;
            nodo->next = tmp;
        }
        if (cambio[position] == NULL)
        {
            cambio[position] = nodo;
            nodo->next = NULL;
        }
        palabras++;
    }
    fclose(diccionario);
    return true;
}

// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
    return *cantidad_palabras;
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    int position = 0;
   for (int i = 0; i < 25; i++)
   {
       if (cambio[position] == NULL)
       {
           *cambio = cambio[position + 1];
           free(cambio[position]);
       }
       else
       {
           for (node *borra = cambio[position]; borra->next != NULL;)
           {
               node *tmp = borra;
               borra = borra->next;
               free(tmp);
           }
       }
   }
   return true;
}

1 Answer 1

0

Did you notice that the words that were being marked as misspelled are all the first words processed for any give letter? That's a clue.

A good step to check functionality is to write a function to print out the entire tree, and call that function at the end of load, using a small dictionary that demonstrates the error. It'll show you if all the words are being processed and where they are in each linked list. Also useful for comparing to which words are being incorrectly marked bad.

So, having done that, and checking how the hash worked, I moved on to the check function. Let's look at part of that code:

for (; comparador->next != NULL; comparador = comparador->next)

When the loop starts for the first time, the code checks the test condition to see if it's true. Now, say that there is exactly one word in the linked list. The address for that node will be at comparador. But what's in comparador->next? Could be another address, could be null. In any case, shouldn't the for loop condition be checking the value in compardor and not comparador->next?

Changing this fixes the code, although I haven't quite figured out why it fails when there are more words in the linked list. I'll leave that for you as an exercise.

Programming note: There are numerous "dead code" lines in the code that can be removed, as well as extraneous lines, and code that can be simplified.

For instance, the lines referring to N and *table vars can probably be removed, since they don't appear to be used.

The for loop I copied above can be combined with the line before it. (The previous line can be plugged into the FOR code as the declaration before the first semicolon.

And, in this, tmp is totally unnecessary. I'll let you figure out how.

     if (cambio[position] != NULL)
    {
        node *tmp = cambio[position];
        cambio[position] = nodo;
        nodo->next = tmp;
    }

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

1
  • Hi, thank you. Yes, you were right those were my problems Commented Sep 18, 2021 at 21:47

You must log in to answer this question.

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