Jessica Li
Jessica Li

Reputation: 11

seg fault in c with pointers

I have two fucntions that prompt the user to print ingredients names for pizza and print them out. But whenever I'm trying to print out the available ingredients, I get a seg fault. And when I prompt to enter ingredients, if I say we have 3 available ingredients today, I can only type 2 in (as shown in the output picture)

    int get_ingredients(char** ingredients,int* num_ingredients) {
        char **ingredients_array = NULL; /*this is an array of pointers points to single ingredient in get_item*/
        int temp,i,j;
        ingredients = &ingredients_array; /*ingredients is a pointer points to the array of pointers*/
        temp = *num_ingredients;
        printf("How many available pizza ingredients do we have today? ");
        scanf("%d",&temp);
        ingredients_array = (char**)calloc(temp, sizeof(char*));
        i = 0;
        printf("Enter the ingredients one to a line: \n");
        while (i < temp){
            *(ingredients_array+i) = get_item();
            i++;
        }
        i = 0;      
        printf("Available ingredients today are: \n");
        while(i < temp) {
            j = i+1;
            printf("%d",j);
            print(". ");
            printf("%s", **(ingredients_array+i));
            i++;
        }
        *num_ingredients = temp;
        return EXIT_SUCCESS;
    }
    char* get_item(){
        int i,a;
        char *each_ingredient= (char*)malloc(61*sizeof(char)); /*points to each input*/
        a = getchar();
        i = 0;
        while (a != EOF && (char)a != '\n'){
            *(each_ingredient+i)= (char)a;
            a = getchar();
            i++;
        }
        *(each_ingredient+i) = '\n';
        return each_ingredient;
    }

This is the output

Upvotes: 0

Views: 130

Answers (1)

Bybit360
Bybit360

Reputation: 166

There are many issues with your get_ingredients question.

  1. The first issue that I noticed is that you changed the pointer of the parameter ingredients, you changed it to the pointer get_ingredients which was set to NULL. So accessing the data from ingredients pointer from now on will get you a segmentation fault, for trying to access an illegal address.
int get_ingredients(char** ingredients,int* num_ingredients) {
        char **ingredients_array = NULL; /*this is an array of pointers points to single ingredient in get_item*/
        int temp,i,j;
        
        //ingredients pointer is lost forever and set to the address of the pointer of ingredients_array
        ingredients = &ingredients_array; /*ingredients is a pointer points to the array of pointers*/
  1. Now the second issue is more of an optimization thing. You set a variable, and then you changed it on the scanf, making the useless to set it to some value initially.
        //Temp is set to num_ingredients, but this is of no use,becuase this value is never used and is overwritten by scanf("%d",&temp);
        temp = *num_ingredients;
        
        printf("How many available pizza ingredients do we have today? ");
        scanf("%d",&temp);
  1. Should allocate pointer of a pointer to char.
ingredients_array = (char**)calloc(temp, sizeof(char*));

Changes

ingredients_array = (char**)calloc(temp, sizeof(char**));
  1. The while loops can be replaced with a for a loop. Which a more appropriate type of loop for this case.
        
        //This can write it better with a for loop
        i = 0;
        printf("Enter the ingredients one to a line: \n");
        while (i < temp){
            *(ingredients_array+i) = get_item();
            i++;
        }
        i = 0;      

        printf("Available ingredients today are: \n");
        //Use for loop intead, because it more appropiate for this case
        while(i < temp) {
            //better to use i+1 instead of j, simply things
            j = i+1;
            //These two printf can be on the same line
            printf("%d",j);
            printf(". ");
            
            //Allocation error?
            printf("%s", **(ingredients_array+i));
            i++;
        }

Using a for loop instead, getting user input from standard function, and using less confusing indexing.

printf("Enter the ingredients one to a line: \n");
//Using for loop
for(int i = 0;i < temp;i++)
{
    char ptr[80]; //Store user input
    scanf("%s", ptr); //Get user input
    ingredients_array[i] = strdup(ptr); //strdup is to make a another string with the same contents
}
        
printf("Available ingredients today are: \n");
for(int i = 0; i < temp;i++)
{
    //These two printf can be on the same line
    printf("%d",i+1);
    print(". ");
            
    //Allocation error?
    printf("%s\n", ingredients_array[i]);
}
  1. *num_ingredients lost its original pointer earlier, so this serves no use.
//This cannot be used because now points to ingredients_array and not to num_ingredients
*num_ingredients = temp;

Now the code with all those changes.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
    
int get_ingredients(char** ingredients,int* num_ingredients) {
        char **ingredients_array = NULL; /*this is an array of pointers points to single ingredient in get_item*/
        int temp;
        
        
        printf("How many available pizza ingredients do we have today? ");
        scanf("%d",&temp);

        
        
        ingredients_array = (char**)calloc(temp, sizeof(char**));
        
        printf("Enter the ingredients one to a line: \n");
        //Using for loop
        for(int i = 0;i < temp;i++)
        {
            char ptr[80]; //Store user input
            scanf("%s", ptr); //Get user input
            ingredients_array[i] = strdup(ptr); //strdup is to make a another string with the same contents
        }
        
        printf("Available ingredients today are: \n");
        for(int i = 0; i < temp;i++)
        {
            printf("%d. ",i+1);   
            printf("%s\n", ingredients_array[i]);
        }
        *num_ingredients = temp;
        
        return EXIT_SUCCESS;
    }
    
    
    
int main()
{
    char** ingredients;
    int a;
    int foo = get_ingredients(ingredients, &a);
    return 0;
}

Output

How many available pizza ingredients do we have today? 4

Enter the ingredients one to a line: 
meat
MEAT
mEaT
no_salas
Available ingredients today are: 
1. meat
2. MEAT
3. mEaT
4. no_salad

Upvotes: 1

Related Questions