Segmentation fault for hash structure if statement [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
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;
}

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.

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.

Related

Hashtable & BST Implementation

I'm working on an assignment that can accept commands from keyboard to insert people into a hashtable. After someone is inserted into the hastable, they can be "friended" with another person in the table. The way I have to store who is friends with who is a binary search tree. What I have to do is for the hashtable the first part of the node would be the person's name, then then next is a pointer to the bst for that person's friends, and finally the end is a pointer to the next node for chaining if there is a collision. Here is a visual example...
I have been able to insert people into my table, but the problem that I can not figure out is how to access the BST and add in friends for that person. Here is my code...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Structures
struct linkedList{
char *name;
struct linkedList *next;
struct linkedList *tree;
};
typedef struct linkedList list;
struct hashTable{
int size;
list **table;
};
typedef struct hashTable hash;
struct bst{
char *val;
struct bst *l;
struct bst *r;
};
int main(){
char input[50];
char *ch, cmd_str[50], name[30];
// Make hash table for names
hash *profiles;
profiles = createHashTable(1001);
while(1){
// Get keyboard input
fgets(input, 50, stdin);
input[strlen(input)-1] = '\0';
// parse the input
ch = strtok(input, " ");
strcpy(cmd_str,ch);
if(strcmp("CREATE", cmd_str) == 0){
ch = strtok(NULL, " \n");
insertPerson(profiles, ch);
}
else if(strcmp("FRIEND", cmd_str) == 0){
ch = strtok(NULL, " \n");
strcpy(name, ch);
ch = strtok(NULL, " \n");
friendPerson(profiles, name, ch);
}
else if(strcmp("UNFRIEND", cmd_str) == 0){
ch = strtok(NULL, " \n");
}
else if(strcmp("LIST", cmd_str) == 0){
ch = strtok(NULL, " \n");
printFriends(profiles, ch);
}
else if(strcmp("QUERY", cmd_str) == 0){
}
else if(strcmp("BIGGEST-FRIEND-CIRCLE", cmd_str) == 0){
}
else if(strcmp("INFLUENTIAL-FRIEND", cmd_str) == 0){
}
else if(strcmp("EXIT", cmd_str) == 0){
printf("\nExiting...\n");
return 0;
}
else{
printf("\nBad Command.\n");
}
}
}
// Creates Hash Table
hash *createHashTable(int size){
int i;
hash *new_table;
if((new_table = malloc(sizeof(hash))) == NULL)
return NULL;
if((new_table->table = malloc(sizeof(list *) * size)) == NULL)
return NULL;
for(i=0; i < size; i++)
new_table->table[i] = NULL;
new_table->size = size;
return new_table;
}
// hashing function
int keyHash(char *name){
int c;
unsigned long key;
while(c = *name++)
key = ((key<<5) + key) + c;
return key%1000;
}
// insert a person into the hash table
void insertPerson(hash *profiles, char *name){
struct linkedList *item = (struct linkedList*)malloc(sizeof(struct linkedList));
int hash_val = keyHash(name);
item->name = name;
item->next = NULL;
item->tree = new_tree;
// Collision case
if(profiles->table[hash_val] != NULL){
while(profiles->table[hash_val]->next != NULL){
profiles->table[hash_val] = profiles->table[hash_val]->next;
}
profiles->table[hash_val]->next = item;
}
// Empty cell
else{
profiles->table[hash_val] = item;
}
}
// friend two people inside the hash table
void friendPerson(hash *profiles, char *name, char *_friend){
int hash1 = keyHash(name);
int hash2 = keyHash(_friend);
// check if the names are already in system
if(!profiles->table[hash1]){
printf("%s is not yet in the system", name);
return;
}
if(!profiles->table[hash2]){
printf("%s is not yet in the system", _friend);
return;
}
// add first friend
if(strcmp(profiles->table[hash1]->name, name) == 0){
insertBST(profiles->table[hash1]->tree, _friend);
}
else{
while(profiles->table[hash1]->next != NULL){
if(strcmp(profiles->table[hash1]->name, name) == 0)){
break;
}
profiles->table[hash1] = profiles->table[hash1]->next;
}
insertBST(profiles->table[hash1]->tree, _friend);
}
// add second friend
if(strcmp(profiles->table[hash2]->name, _friend) == 0){
insertBST(profiles->table[hash2]->tree, name);
}
else{
while(profiles->table[hash2]->next != NULL){
if(strcmp(profiles->table[hash2]->name, name) == 0)){
break;
}
profiles->table[hash2] = profiles->table[hash1]->next;
}
insertBST(profiles->table[hash2]->tree, name);
}
}
// creates a new bst node
struct bst *newBSTNode(char *name){
struct bst *temp = (struct bst* )malloc(sizeof(struct bst));
temp->val = strdup(name);
strcpy(temp->val, name);
temp->l = temp->r = NULL;
return temp;
}
// Inserts the a friend into a BST
struct bst *insertBST(struct bst *node, char *name){
if(!node)
return newBSTNode(name);
else{
if(strcmp(name, node->val) < 0){
node->l = insertBST(node->l, name);
}
else if(strcmp(name, node->val) > 0){
node->r = insertBST(node->r, name);
}
}
return node;
}
// Inorder print of names
void inorder(struct bst *root){
if(!root){
inorder(root->l);
printf("%s ", root->val);
inorder(root->r);
}
}
// Sends to function to print names
void printFriends(hash *profiles, char *name){
int hash_val = keyHash(name);
inorder(profiles->table[hash_val]->tree);
}
How would I be able to access the BST of said person? The struct bst *tree = profiles->table[hash1]->tree; was my previous attempt, but it was more of a shot in the dark. Thanks in advance!
Update: Okay, so I have been able to add friends (I think) and now I'm trying to print them with void printFriends(). However when I run the function nothing prints out. Would anyone know where I'm messing it up? I've updated the code above.
Your linkedList stores the name and a tree pointer. But the type of tree is linkedList. Change that to struct bst *. You'll have to reorder the declarations, or insert a forward declaration.
Implement a search. You check if the hash buckets are empty, but you don't search for the matching name.
Once you find a matching name in the bucket, the same node contains the aforementioned tree pointer. Insert the friend in the tree. Depending on your logic, you may or may not want to insert a backreference in the other person's tree. (If Alice is friends with Bob, does that make Bob friends with Alice automatically? Or wait for confirmation?)

Why does the root change its data? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Here is are the three structures that I'm using and for instance when my program
gets 'the' as the first word, it makes *rt->str = the.
However when the next word is read, the key is equal to to the *rt->str and I don't understand why. I'm a c programmer beginnner and this has really stoppped me in my tracks.
struct node {
char *str;
int occ;
struct node *sibling;
struct node *child;
};
struct node* root;
struct node* getNew(char word[100]) {
struct node *newNode;
newNode = (struct node *)malloc(sizeof(struct node));
newNode->str = word;
newNode->sibling = NULL;
newNode->child = NULL;
newNode->occ = 0;
return newNode;
}
struct node* insert( char key[100], struct node **rt ){
if(*rt == NULL) {
*rt = getNew(key);
printf("This is the key in the root: %s\n", (*rt)->str);
return *rt;
}else{
printf("root word: %s\n", (*rt)->str);
exit(0);
}
struct node *leaf = *rt;
int n = 0;
int i;
char w2[100];
strcpy(w2, key);
printf("root word: %s\n", (*rt)->str);
for(i = 0; i < strlen((leaf)->str); i++) {
printf("%c %c \n", (leaf)->str[i], key[i]);
if((key[0] == (leaf)->str[i])) {
n++;
key = key + 1;
printf("key is: %s \n", key);
}
}
if(key[0] == 0) {
printf("key is empty \n");
}
printf("This is the word after for loop: %s \n", key);
exit(0);
}
This:
newNode->str = word;
doesn't copy the string (as in, the characters that build up the string), it just copies the location of a string, which is an argument. That location will not remain valid when the function exits, so this gives you undefined behavior when you access it later.
C does not support assigning arrays, and arrays are not pointers.

Getting a segmentation fault. Can't figure out why

I'm making a phonebook program with a binary search tree. Whenever I try to input a new data, the segmentation fault occurs. First, I have type definition structure which name is phoneData.
typedef struct phoneData {
char name[NAME_LEN];
char phoneNum[PHONE_LEN];
struct phoneData *right, *left;
} phoneData;
void InputPhoneData()
{ //phoneData *pData;
char name[NAME_LEN];
char phoneNum[PHONE_LEN];
/*if ((pData = (phoneData*)malloc(sizeof(phoneData))) == NULL) {
fprintf(stderr, "Memory Allocation failed\n");
return;
}*/
fputs("이름 입력: ", stdout);
if (fgetString(name, NAME_LEN, stdin) == 1) {
getchar();
return;
}
fputs("전화번호 입력: ", stdout);
if (fgetString(phoneNum, PHONE_LEN, stdin) == 1) {
getchar();
return;
}
insert_node(name, phoneNum);
numOfData++;
fputs("입력이 완료되었습니다.", stdout);
getchar();
}
And this is the function which I call to input a data. Please don't mind the Korean sentences. In the function, I call another function insert_node. This is the function which inserts the binary search tree node.
void insert_node(char name[], char phoneNum[])
{
phoneData *p, *t;
phoneData *n;
t = *root;
p = NULL;
while (t != NULL) {
if (strcmp(name, t->name) == 0)
return;
p = t;
if (strcmp(name, p->name) < 0)
t = p->left;
else
t = p->right;
}
n = (phoneData*)malloc(sizeof(phoneData));
if (n == NULL)
return;
strcpy(n->name, name);
strcpy(n->phoneNum, phoneNum);
n->left = n->right = NULL;
if (p != NULL) {
if (strcmp(p->name, name) < 0)
p->left = n;
else
p->right = n;
}
else
*root = n;
}
I'm still wondering which is the part that I'm getting a segmentation fault. I already checked the fgetString function, and it seems to be okay. Did I make any mistakes on InputPhoneData function or insert_node function?
And by the way, the variable 'root' is a global variable which is a double pointer initialized as NULL. (phoneData **root = NULL;)
That's your problem right there. *root will dereference a NULL pointer.
Change the declaration to:
phoneData *root = NULL;
and replace *root with root and root with &root in the rest of your code.
It will be easy, fun and interesting to debug such kind of issues.
Try to debug using gdb :)
You can check following link,
http://www.thegeekstuff.com/2010/03/debug-c-program-using-gdb

Singly linked list C, printing

I'm a beginner in developing, so my sensei gave me a task to complete in which I need to enter a couple of strings in linked lists and after I enter print, they need to be printed in the correct order, from the first to last.
Here is what I got:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
char data;
struct Node *next;
}node;
char createlist(node *pointer, char data[100]) {
while (pointer->next != NULL) {
pointer = pointer->next;
}
pointer->next = (node*) malloc(sizeof(node));
pointer = pointer-> next;
pointer->data = *data;
pointer->next = NULL;
}
int main() {
node *first, *temp;
first = (node*) malloc(sizeof(node));
temp = first;
temp->next = NULL;
printf("Enter the lines\n");
while (1) {
char data[100];
gets(data);
createlist(first, data);
if (strcmp(data, "print") == 0)
printf("%s\n", first->data);
else if (strcmp(data, "quit") == 0)
return (0);
};
}
When I run it I get:
Enter the lines:
asdfasdf
print
(null)
Any help would be appreciated since this is my first time using linked lists.
You should format your code properly.
first->data is allocated via malloc() and isn't initialized, so using its value invokes undefined behavior.
In order not to deal the first element specially, you should use pointer to pointer to have createlist() modify first.
Since createlist() won't return anything, type of its return value should be void.
I guess you wanted to copy the strings instead of assigning the first character of each strings.
To print all of what you entered, code to do so have to be written.
You shouldn't use gets(), which has unavoidable risk of buffer overrun.
You should free() whatever you allocated via malloc().
improved code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
char *data;
struct Node *next;
} node;
void createlist(node **pointer, char data[100])
{
while (*pointer != NULL)
{
pointer = &(*pointer)->next;
}
*pointer = malloc(sizeof(node));
if (*pointer == NULL)
{
perror("malloc 1");
exit(1);
}
(*pointer)->data = malloc(strlen(data) + 1);
if ((*pointer)->data == NULL)
{
perror("malloc 2");
exit(1);
}
strcpy((*pointer)->data, data);
(*pointer)->next = NULL;
}
int main(void)
{
node *first = NULL;
printf("Enter the lines\n");
while (1)
{
char data[100], *lf;
if (fgets(data, sizeof(data), stdin) == NULL) strcpy(data, "quit");
if ((lf = strchr(data, '\n')) != NULL) *lf = '\0'; /* remove newline character */
createlist(&first, data);
if (strcmp(data, "print") == 0)
{
node *elem = first;
while (elem != NULL)
{
printf("%s\n", elem -> data);
elem = elem->next;
}
}
else if (strcmp(data, "quit") == 0)
{
while (first != NULL)
{
node *next = first->next;
free(first->data);
free(first);
first = next;
}
return(0);
}
}
}
Inside createlist(), you are iterating to the end of the list. There, you are adding a new node and setting a new text entered. By doing so, you are missing that you have already a first node. Because you are iterating to the end in every call of createlist(), you are jumping over your first node every time, so it remains without text and delivers NULL.
In order not to jump over the first initial node, you could alter createlist() like this:
char createlist(node *pointer, char data[100])
{
while (pointer->data != NULL && pointer->next != NULL)
{
pointer = pointer->next;
}
...
...
}
Or you could create the first node not initially, but only after the first line of text was entered.
edit: Here are two additional style hints:
What happens if somebody enters 120 characters? The text will outrun your char[100] array and will fill RAM that is used otherwise. This is a buffer overflow. You could try to grab only the first 100 chars, get the substring. Alternatively, use the length argument of fgets()
Create a constant for 100, like #define MAX_BUFFER_LENGTH 100, and use it every time.

Can't pinpoint Segmentation fault [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Seg Fault in Knowledge Tree
I can't pinpoint my seg fault in my information tree. It is supposed to read from file or get user input if the file does not exist. It's supposed to guess the animal based on yes or no questions. I have limited experience with c so any help would be greatly appreciated.
.c file
#include<stdio.h>
#include<stdlib.h>
#include"animal.h"
#include<string.h>
#include<assert.h>
/*returns a new node for the given value*/
struct Node * newNode (char *newValue)
{
printf("Node test");
struct Node * tree;
tree = (struct Node*)malloc(sizeof(struct Node));
tree -> value = newStr(newValue);
printf("Node test");
return tree;
}
/* returns a new string with value passed as an argument*/
char * newStr (char * charBuffer)
{
printf("Str test");
char *newstr;
if(charBuffer[0] == 'A' || charBuffer[0] == 'Q'){
newstr = strdup(&charBuffer[1]);
}else{
newstr = strdup("");
}
return newstr;
}
/*Read from a File and create a tree*/
struct Node * readATree(FILE * f)
{
printf("ReadATree test");
char c;
char buffer[100];
struct Node * newTree;
c = fgetc(f);
if (c == 'A'){
fgets(buffer, 100, f);
newTree = newNode(newStr(buffer));
newTree -> left = NULL;
newTree -> right = NULL;
}
else{
fgets(buffer, 100, f);
newTree = newNode(newStr(buffer));
newTree->left = readATree(f);
newTree->right = (struct Node *) readATree(f);
}
return newTree;
}
/*Write Tree to a File*/
void writeAFile(struct Node* tree, FILE * f)
{
printf("WriteFile test");
char buffer[100];
strcpy(buffer, tree->value);
if(tree != 0){
if(tree->left == NULL && tree->right == NULL){
fputc('A', f);
fputs(buffer,f);
} else{
fputc('Q',f);
fputs(buffer,f);
writeAFile(tree->left, f);
writeAFile(tree->right,f);
}
}
}
/*The play should start from here*/
int main (){
printf("main test");
struct Node* node;
struct Node* root;
char ans[100];
char q[100];
FILE * f;
f = fopen("animal.txt", "r+");
if(f != NULL)
readATree(f);
else{
node = newNode("Does it meow?");
node->right = NULL;
node->right->right=NULL;
node->left->left=NULL;
node->left=newNode("Cat");
root = node;
}
while(node->left != NULL && node->right != NULL){
printf(node->value);
scanf(ans);
if(ans[0] == 'Y' || ans[0] == 'y')
node = node->left;
else if(ans[0] == 'N' || ans[0] == 'n')
node = node->right;
else
printf("That is not a valid input.\n");
}
if(ans[0] == 'Y' || ans[0] == 'y')
printf("I win!");
else if(ans[0] == 'N' || ans[0] == 'n'){
printf("What is your animal?\n");
scanf("%s",ans);
printf("Please enter a yes or no question that is true about %s?\n", ans);
scanf("%s",q);
node->right = newNode(q);
node->right->left = newNode(ans);
node->right->right = NULL;
}
writeAFile(root,f);
fclose(f);
return 0;
}
.h
#include<stdio.h>
struct Node {
char *value;
struct Node * left;
struct Node * right;
};
struct Node * newNode (char *newValue) ;
char * newStr (char * charBuffer);
struct Node * readATree(FILE * f);
void writeAFile(struct Node* tree, FILE * f);
Don't force the good people of SO to wade through and debug your code! Also, don't keep repeating your question. The reason it wasn't answered to your satisfaction earlier is that people were unwilling to compensate for your laziness.
That's what debuggers are for. Run your code in a debugger, and it will tell you when you're accessing a null pointer.
If you don't have a debugger, throw a bunch of print statements into your program. If you run your program, the last printout before the crash will be just above the place where your segmentation fault occurred. You may want to add even more print statements near that point, perhaps dumping out some pointer values.
From a cursory glance at the code:
node->right = NULL;
node->right->right=NULL;
The second line here will access a NULL pointer, which will cause a segfault.
In general, running the code in a debugger will let you see which line caused the error.
I'm guessing that these warnings are a clue:
animal.c: In function ‘main’:
animal.c:95: warning: format not a string literal and no format arguments
animal.c:96: warning: format not a string literal and no format arguments

Resources