-1

The strcasecmp in my check()-function (top of the code) does not work as it should. When I run the code, it does NOT act caseinsensitively. I think it's something about the types that I compare but I couldn't figure it out yet... PS: It's from CS50 but I already submitted the problem, so no cheating here ;)

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.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 = 1000; //CHANGE THIS ACCORDING TO HASH ALGORITHM


// Hash table
node *table[N];

// used for size() to keep track of dictionary size
int dict_size = 0;


// Returns true if word is in dictionary (case-insensitive), else false
bool check(const char *word)
{

    //1: hash word to obtain hash value
    //2: access linked list at that index in hash table
    //cursor = first item of linked list

    node *cursor = table[hash(word)];



    //then move the cursor until it's NULL
    //use cursor (cursor = cursor->next) to traverse through linked list

    //true if word found

    while(cursor != NULL)
    {

        //has to be ZERO! strcasecmp returns numbers if the words differ, not true or false

        if (strcasecmp(cursor->word, word) == 0)
        {
            return true;
        }
        cursor = cursor->next;
    }



    //false if reached NULL and word has not been found

    return false;
}




//Hashes word to a number
//takes word as input
//outputs a number corresponding to which "bucket" (index in an array) to store the word
//could do first letter, first two letters, MATH??? ---> SEARCH ONLINE AND GIVE THE SOURCE
unsigned int hash(const char *word)
{


    //make it deterministic
    //use SDBM Hash Function from source
    unsigned hashval;

    for (hashval = 0; *word != '\0'; word++)
    {
        hashval = *word + 31 * hashval;
    }
    return hashval % N;


    //SOURCE: https://stackoverflow.com/questions/7666509/hash-function-for-string
}




// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{

    //1: open dict file
    FILE *dict = fopen(dictionary, "r");
    char expression[LENGTH + 1];

    //check for return value NULL
    if (dict == NULL)
    {
        printf("Could not open file!");
        return false;
    }


    //FOR EVERY WORD IN DICT!

    //2: read strings ("expression") from file one at a time
    //do until fscanf returns EOF
    while (fscanf(dict, "%s", expression) != EOF)
    {

        //count words (in global variable) to determine size of dict
        dict_size++;


        //3: create a new node for each word
        //use malloc to make new node
        //check for NULL
        //strcpy word into node
        node *new_node = malloc(sizeof(node));
        if (new_node == NULL)
        {
            printf("Not enough memory for malloc");
            return false;
        }

        strcpy(new_node->word, expression);
        new_node->next = NULL;


        //4: hash word to obtain a hash value
        //use hash function
        //this will return an index (alphabet-index)

        //5: insert node into hash table at that locatíon
        //index into hashtable to get linkedlist that you want to add word into
        //set pointers to correct order!!!
        //first point from new_node to node-number1 and then from head to new_node to not "lose" the list


        new_node->next = table[hash(expression)];
        table[hash(expression)] = new_node;
    }



    //first: allocate memory for new node
    // node *n = malloc(sizeof(node));
    // strcpy(n->word, "HELLO") --> change to different from hello
    // n->next = NULL

    //load all words from dict into a hash table
    //stop when node->next == NULL

    //array of linked lists (each of which represents an char (a,b,c,d, ...))
    //need to use datatype "node"
        //needs hash function
        //takes word (e.g. "apple") and outputs, which is the starting char


    // return true if successfully loaded into memory

    fclose(dict);
    return true;
}
Dimianovic
  • 13
  • 1
  • why don't you use strcmp? as far as i know its case sensitive. also, you can check it yourself, strcasecmp is not case sensitive – Asaf Itach Mar 18 '21 at 06:37
  • `strcasecmp()` is not case sensitive, but your hash function will give different values for the same words with different case. So if the case doesn't match, you end up looking in the wrong bucket. – Dmitri Mar 18 '21 at 06:46

1 Answers1

0

EDIT: I figured out, that I can take tolower() in the hashing function to fix the problem. But honestly I don't have a clue, why this works now...

unsigned int hash(const char *word)
{


    //make it deterministic
    //use Hash Function from source
    unsigned hashval;

    for (hashval = 0; *word != '\0'; word++)
    {
        hashval = tolower(*word) + 31 * hashval;
    }
    return hashval % N;


    //SOURCE: https://stackoverflow.com/questions/7666509/hash-function-for-string
}
Dimianovic
  • 13
  • 1