0

the problem is that when I try to copy the name from "Buffer" to the "Node" using "sprintf" I always get "segmentation fault" !!.

THE CODE:

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

//node declaration:
typedef struct node
{
    char* name[20];
    struct node* link;
}
node;

unsigned int hash(char* buffer ,unsigned int CAPACITY) ;

int main(int argc , string argv[])
{
    //declarations:
    FILE* fp = fopen("us-names.txt" , "a+") ;
    if(fp == NULL)
    {
        printf("CANNOT OPEN THE FILE !\n") ;
        return 1 ;
    }

    char buffer[20] ;
    unsigned int key = 0;
    unsigned int CAPACITY = 100 ;
    struct node* temp = NULL ;
    struct node* hashtable[CAPACITY] ;

    //Import name from the FILE & store into buffer:
    fgets(buffer , 20 , fp) ;
    //pass the name into the hash_function and get the key:
    key = hash(buffer , CAPACITY) ;

    //put the name in a node then in it's right place in the hashtable using the key:
    temp = malloc(sizeof(struct node)) ;
    sprintf(*temp->name , "%s" , buffer) ;
    hashtable[key] = temp ;

    //close the FILE & return 0:
    fclose(fp) ;
    return 0;
}

unsigned int hash(char* buffer , unsigned int CAPACITY)
{
    unsigned int sum = 0 ;
    for(int i = 0; buffer[i] != '\0' ;i++)
    {
        sum += buffer[i] ;
    }
    return sum % CAPACITY ;
}

when I debug my program it shows me that the problem is at this line : sprintf(*temp->name , "%s" , buffer) ;

and I've tried too many ways to fix it put all of them didn't work !!

I obviously don't know what to do ,I hope some one can help :(

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Moe Hasan
  • 11
  • 2

1 Answers1

2

These two lines are problematic, and at the same time mask each others contribution to the issue:

char* name[20]; //first member of struct  
//and
sprintf(*temp->name , "%s" , buffer) ;

The issue being that both contribute equally to the potential that your code will attempt writing to memory that it does not own, thus invoking undefined behavior, and subsequently your observed seg-fault.
Together, although they will not allow your code to work, will allow a clean compile. Removing the * from either one of them (not both) will result in a warning message during compile. Removing both will allow a clean compile, and allow the sprintf() call to work properly. Here is why...

This:

char* name[20]; 

creates 20 instances of uninitialized pointers to char ( char * ). Attempting to write to any one of them will will result in undefined behavior.

Change it to char name[20];//removing the *

At this point, after having removed the asterisk above, the second error is unmasked, and an attempted compile would generate a warning such as this:

"warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'char *'; remove *"

To address this change:

sprintf(*temp->name , "%s" , "some value") ;

To:

sprintf(temp->name , "%s" , "some value");//removed asterisk
ryyker
  • 22,849
  • 3
  • 43
  • 87