0

I decided that I wanted to make a program in C that would take a user input and do things with a hash table... When I go to put in something it gets a segmentation fault at line 32. This being the following:

if (!hashTable[hashIndex].head) {

Rest of code:

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

  struct hash *hashTable = NULL;
  int eleCount = 0;

  struct node {
        int key;
        char name[1024];
        struct node *next;
  };

  struct hash {
        struct node *head;
        int count;
  };

  struct node * createNode(int key, char *name) {
        struct node *newnode;
        newnode = (struct node *)malloc(sizeof(struct node));
        newnode->key = key;
        strcpy(newnode->name, name);
        newnode->next = NULL;
        return newnode;
  }


  void insertToHash(int key, char *name) {
        int hashIndex = key % eleCount;
        struct node *newnode =  createNode(key, name);
        if (!hashTable[hashIndex].head) {
                hashTable[hashIndex].head = newnode;
                hashTable[hashIndex].count = 1;
                return;
        }
        newnode->next = (hashTable[hashIndex].head);
        hashTable[hashIndex].head = newnode;
        hashTable[hashIndex].count++;
        return;
  }
  void deleteFromHash(int key) {
        int hashIndex = key % eleCount, flag = 0;
        struct node *temp, *myNode;
        myNode = hashTable[hashIndex].head;
        if (!myNode) {
                printf("Word not in hash Table!!\n");
                return;
        }
        temp = myNode;
        while (myNode != NULL) {
                if (myNode->key == key) {
                        flag = 1;
                        if (myNode == hashTable[hashIndex].head)
                                hashTable[hashIndex].head = myNode->next;
                        else
                                temp->next = myNode->next;

                        hashTable[hashIndex].count--;
                        free(myNode);
                        break;
                }
                temp = myNode;
                myNode = myNode->next;
        }
        if (flag)
                printf("Word deleted from Hash Table by the power of Grey Skull\n");
        else
                printf("Word is not present in hash Table!\n");
        return;
  }

  void searchInHash(int key) {
        int hashIndex = key % eleCount, flag = 0;
        struct node *myNode;
        myNode = hashTable[hashIndex].head;
        if (!myNode) {
                printf("Searched word not in hash table\n");
                return;
        }
        while (myNode != NULL) {
                if (myNode->key == key) {
                        printf("Key      : %d\n", myNode->key);
                        printf("Name     : %s\n", myNode->name);
                        flag = 1;
                        break;
                }
                myNode = myNode->next;
        }
        if (!flag)
                printf("Searched word not in hash table\n");
        return;
  }

  void display() {
        struct node *myNode;
        int i;
        for (i = 0; i < eleCount; i++) {
                if (hashTable[i].count == 0)
                        continue;
                myNode = hashTable[i].head;
                if (!myNode)
                        continue;
                printf("Key         Word\n");
                printf("----------------\n");
                while (myNode != NULL) {
                        printf("%-12d", myNode->key);
                        printf("%-15s", myNode->name);
                        myNode = myNode->next;
                }
        }
        return;
  }

  int main() {
        int elecount, ch, key, i;
        char name[1024],cas[5];
        eleCount = 23;
        hashTable = (struct hash *)calloc(elecount, sizeof (struct hash));
        while (1) {
                printf("\nword: Insert word\n#d: word Delete word\n");
                printf("#s word: Search for word\n#p: Display hash table\n#Q: Exit\n");
                printf("Enter your choice:");
                fgets(name, 1023, stdin);
                if(sscanf(name,"#d",&cas)==1)
                    {//delete
                    i=2;
                    while("name[i]"!="\n")
                    {key=key+i;
                    i++;}
                    deleteFromHash(key);
                    }
                else if(sscanf(name,"#s",&cas)==1)
                    {//search
                    i=2;
                    while("name[i]"!="\n")
                    {key=key+i;
                    i++;}
                    searchInHash(key);
                    }
                else if(sscanf(name,"#p",&cas)==1)
                    {//print
                    display();
                    }
                else if(sscanf(name,"#Q",&cas)==1)
                    {//Quit
                    exit(0);
                    }
                else
                    {//insert
                    while("name[i]"!="\n")
                    {key=key+i;
                    i++;}
                    name[strlen(name) - 1] = '\0';
                    insertToHash(key, name);
                    }
                }

        return 0;
  }
Gvalder
  • 74
  • 7

2 Answers2

1

Here is what I see as problems with the posted code:

1) the first parameter to calloc() is not initialized

2) the returned value from calloc is not checked to assure operation was successful

3) the returned value from calloc was cast and it should not be

4) the 'ch' variable is unused

5) this line: while("name[i]"!="\n") should be: while( name[i] != '\n')

6) the returned value form fgets() is not checked to assure successful operation

7) the format strings for the sscanf() statements are using '#' when they should be using '%'

8) variable eleCount not used

9) the struct definitions 'node' and 'hash' need to be before any usage of those definitions

10) the returned value from malloc should not be cast

11) the returned value from malloc is not checked to assure successful operation

12) the lines like this: 'else if(sscanf(name,"#Q",&cas)==1)' are not correct. they should be similar to:

else if(sscanf(name,"#Q",&cas)!=1)
{ // then sscanf failed
    perror( "sscanf failed" );
    exit( EXIT_FAILURE );
}

// implied else, sscanf successful

....

13) given the input description and the code following the calls to sscanf(), the sscan only needs to be called for a char input '%c' then a switch statement on that char. the cases of the switch statement would be the checks for the various commands for those commands that need a 'name' to operate with, then there needs to be a if( 1 != sscanf( name, " %s", &cas ) ) // handle error // implied else // apply command to the input name

14) the array 'cas[]' only has 5 char elements so if a parameter is greater than 4 characters then there will ve a buffer overrun, resulting in undefined behaviour and can/will lead to a seg fault event.

15) I think this line: 'key=key+i;' is not doing what the OP expects.

16) i think this line: 'insertToHash(key, name);' is not doing what the OP expects

I think I understand what the OP was trying to accomplish, but the posted code is not even close and does not even come close to compiling.

Suggest OP enable all warnings in their compiler, fix the warnings and errors,then do some reasonable debug activity, then if they still are having problems, then repost the question.

user3629249
  • 16,402
  • 1
  • 16
  • 17
0

As others already said, your calloc in the main function uses the uninitialized variable elecount instead of eleCount. I recommend not using the same name for global and local variables with the only difference being the capitalization. You see why.

Also before you check the .head component you should check the variable itself.

So first check for hashTable, then you do the other check. Otherwise you might check a components existence at NULL.

rfreytag
  • 1,203
  • 11
  • 18