Home > Software engineering >  Hash Table Not Working Because of Segmentation Fault
Hash Table Not Working Because of Segmentation Fault

Time:10-25

I just learned about hash tables today and I tried to make one in C. I get a segmentation fault at line 90. It seems to store the data and retrieve the data fine. It's just when I try to use strcpy to copy the value in the data to a string in the calling function that I get a segmentation fault. I'm not really sure why this is happening since the data is printing out fine.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define size 100


//creates the lsit where the hash table will be stored

float round(int conver){
  conver = conver*10.0f;
  conver = (conver > (floor(conver) 0.5f)) ? ceil(conver) : floor(conver);
  conver = conver/10.0f;

  //If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
  //conver = roundf(conver*10.0f)/10.0f;

  return conver;
}

int hash(char input[]){
    //decides where a string should be stored
    float number = 0;
    for(int i = 0; i < strlen(input); i  ){
        int toAdd = input[i];
        printf("to add: %d", toAdd);
        number = number   toAdd;
        printf("number: %f", number);
    }
    printf("number again: %f", number);
    number /= strlen(input);
    number = round(number);
    printf("number divided: %f \n", number);
    return number;
}


struct Node{
    //blueprint for linked list node
    struct Node *Next;
    char data[];

};

struct Node *hashTable[];

struct Node *createNode(char *data){
    //utility function to create a node in the linked list
    struct Node *newNode = malloc(sizeof(struct Node));
    newNode->Next = NULL;
    strcpy(newNode->data, data);


    return newNode;
};



void createHashTable(){
    //creates the hash table before anything can be inserted
    for(int i = 0; i < size; i  ){
        hashTable[i] = NULL;
    }
}

void addToHashTable(char *input){
    //adds to the hash table
    int hashed = hash(input);
    if(hashTable[hashed] == NULL){
        hashTable[hashed] = createNode(input);
    }
    else{
        struct Node *newNode = createNode(input);
        newNode->Next = hashTable[hashed];
        hashTable[hashed] = newNode;
    }
}

char *search(char input[], char *writeTo){
    //searches the hash table for a value
    int hashed = hash(input);
    printf("\nhashed: %d", hashed);
    printf("\ndata: %s", hashTable[hashed]->data);
    if(hashTable[hashed] == NULL){
        strcpy(writeTo, "not found");
        return;
    }
    else if(hashTable[hashed]->Next == NULL){
        printf("\nit is: %s", hashTable[hashed]->data);
        strcpy(writeTo, hashTable[hashed]->data);
        return;
    }
    else{
        struct Node *newNode = hashTable[hashed];
        while(newNode != NULL){
            if(newNode->data == input){
                strcpy(writeTo, hashTable[hashed]->data);
                return;
            }
            newNode = newNode->Next;
        }
    }
}

int main()
{
    //main function
    createHashTable();
    addToHashTable("124");
    char *writeTo;
    search("124", writeTo);
    printf("%s", writeTo);

    return 0;
}

CodePudding user response:

First of all, when I run your code I don't get a segfault. Did you remove the use case where the segfault occured? If not, it could be a difference in our environments.

More importantly, your code seems to be riddled in small problems. If you get to fixing those one by one, then the important logical errors will have nowhere to hide.

Here is a (n unordered and incomplete) list of such problems:

In your round function, you are using floor and ceil, but you never include the math library.

In your search function, you are not returning a char*, you are returning nothing. The function header should reflect that.

In your search function, in the final else statement, in the while loop, the condition of the if statement compares two char* values, whereas I assume you mean to compare two strings.

In some of your print statements, you are not printing a new line or any other whitespace, making the results hard to read.

CodePudding user response:

There were some bugs in it.

This code should work. I tried to change your code as minimal as possible.

Dont forget that you have to free() pointerstructures.

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"


#define size 100


int _round(float conver){
  
  conver = (conver > (floorf(conver) 0.5f)) ? ceilf(conver) : floorf(conver);
  return (int) conver;
}

int hash(char input[]){
    float number = 0;
    for(int i = 0; i < strlen(input); i  )
    {
        int toAdd = (int) input[i];
        number = number   toAdd;
    }
    number /= strlen(input);
    number = _round(number);
    return number;
}


struct Node{
    struct Node *Prev;
    struct Node *Next;
    char *data;
};

struct Node *hashTable[size];

struct Node *createNode(char data[]){
    struct Node *newNode = malloc(sizeof(struct Node));
    newNode->Prev = NULL;
    newNode->Next = NULL;
    newNode->data = malloc( sizeof(char) * (strlen(data)));
    strcpy(newNode->data, &data[0]);
    


    return newNode;
};



void createHashTable(){
    for(int i = 0; i < size; i  ){
        hashTable[i] = NULL;
    }
}

void addToHashTable(char input[]){
    int hashed = hash(input);
    if(hashTable[hashed] == NULL){
        hashTable[hashed] = createNode(input);
    }
    else{
        struct Node *newNode = createNode(input);
        newNode->Next = hashTable[hashed];
        hashTable[hashed]->Prev = newNode;
        hashTable[hashed] = newNode;
    }
}

char *search(char input[]){
    
    int hashed = hash(input);
    printf("hashed: %d\n", hashed );
    if(hashTable[hashed] == NULL){
        char *writeTo = malloc( sizeof( char ) * 9);
        strcpy(writeTo, "not found");
        return writeTo;
    }
    else if(hashTable[hashed]->Next == NULL){
        char *writeTo = malloc( sizeof(char) * (strlen(input)));
        strcpy(writeTo, hashTable[hashed]->data);
        return writeTo;
    }
    else{
        struct Node *newNode = hashTable[hashed];
        char *data = malloc( sizeof( char) * (strlen(input)));
        strcpy( data, &input[0] );
        data[strlen(input)] = '\0';
        while(newNode != NULL){
            if(strcmp(newNode->data, data) == 0 ){
                char *writeTo = malloc( sizeof(char) * (strlen(input)));
                strcpy(writeTo, newNode->data);
                return writeTo;
            }
            newNode = newNode->Next;
        }
        free( data );
    }

    char *writeTo = malloc( sizeof( char ) * 9);
    strcpy(writeTo, "not found");
    return writeTo;
}

void freeHashTable()
{
  struct Node * node;
  for( int i = 0; i < size;   i )
  {
    node = hashTable[i];

    if( node != NULL )
    {
      while( node->Next != NULL )
      {
        node = node->Next;
      }

      while( node->Prev != NULL )
      {
        node = node->Prev;
        free( (void*) node->Next->data );
        free( (void*) node->Next );
      }
      free( (void*) node->data );
      free( (void*) node ); 
    }
  }
}

int main()
{
    
    createHashTable();
    addToHashTable("142");
    addToHashTable("124");
    char *writeTo;
    writeTo= search("142");
    printf("%s\n", writeTo );
    free( (void*) writeTo);
    writeTo = search( "124" );
    printf("%s\n", writeTo);
    free( (void*) writeTo);
    freeHashTable();

    return 0;
}
  •  Tags:  
  • c
  • Related