user13059000
user13059000

Reputation:

How can I increase the array size with malloc?

I tried to make a function that add a member in an array of struct and then increase its dimension.

void addMember(id **list, size_t *size)
{
    (*size)++;
    *list = *size == 1 ? malloc(sizeof(id)) : realloc(*list, *size * sizeof(id));

    if(!list) {
        printf("Dynamic allocation failed.\n");
        exit(1);
    }
    
    list[*size-1]->name = malloc (30 * sizeof(char));
    list[*size-1]->surname = malloc (30 * sizeof(char));
    list[*size-1]->number = malloc (15 * sizeof(char));

    if(!list[*size-1]->name || !list[*size-1]->surname || !list[*size-1]->number) {
        printf("Dynamic allocation failed.\n");
        exit(1);
    }

    printf("Name: ");
    fgets(list[*size-1]->name, 30, stdin);
    list[*size-1]->name[strcspn(list[*size-1]->name, "\n")] = 0;
    list[*size-1]->name = realloc (list[*size-1]->name, strlen(list[*size-1]->name) + 1 * sizeof(char));

    if(strcmp(list[*size-1]->name, "") == 0) {
        printf("You did not enter the name. Try again.\n");
        free(list[*size-1]->name);
        (*size)--;
        *list = realloc(*list, *size * sizeof(id));
        return;
    }

    printf("Surname: ");
    fgets(list[*size-1]->surname, 30, stdin);
    surname[*size-1]->surname[strcspn(list[*size-1]->surname, "\n")] = 0;
    surname[*size-1]->surname = realloc (list[*size-1]->surname, strlen(list[*size-1]->surname) + 1 * sizeof(char));

    if(strcmp(list[*size-1]->surname, "") == 0) {
        printf("You did not enter the surname. Try again.\n");
        free(list[*size-1]->surname);
        (*size)--;
        *list = realloc(*list, *size * sizeof(id));
        return;
    }

    printf("Number: ");
    fgets(list[*size-1]->number, 15, stdin);
    list[*size-1]->number[strcspn(list[*size-1]->number, "\n")] = 0;
    list[*size-1]->number = realloc (list[*size-1]->number, strlen(list[*size-1]->number) + 1 * sizeof(char));

    if(strcmp(list[*size-1]->number, "") == 0) {
        printf("You did not enter the number. Try again.\n");
        free(list[*size-1]->number);
        (*size)--;
        *list = realloc(*list, *size * sizeof(id));
        return;
    }
}

However I ran into a problem when I try to add the second member to the array. In fact, during the second call, the program returns me an EXC_BAD_ACCESS error here: list[*size-1]->name = malloc (30 * sizeof(char));. On the contrary, I can enter the first array member without any problem. How can I solve that? The struct is:

typedef struct {
    char *name;
    char *surname;
    char *number;
} id;

EDIT:

This is the main file:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "functions.h"

int main()
{
    id *list = NULL;
    size_t i, size = 0;
    int choice;
    srand((unsigned)time(NULL));
    
    do {
        printf("Enter '1' to display all members, enter '2' to add a new member, enter '3' to exit: ");
        scanf("%d%*c", &choice);
        putchar('\n');
        
        switch(choice) {
            case 1:
                if(size == 0)
                    printf("There's no members.\n");
                else
                    for(i = 0; i < size; i++)
                printf("%s %s\n", list[i].name, list[i].surname);
                break;
                
            case 2:
                if(size < 30)
                    addMember(&list, &size);
                break;
        }
        
        printf("Press start.");
        getchar(); putchar('\n');
        
    } while(choice != 3);
    
    free(list);
    
    return 0;
}

Upvotes: 0

Views: 301

Answers (1)

001
001

Reputation: 13533

list is a pointer to an array of id so it should be: (*list)[*size-1].name, etc. You could save some trouble and create some temp vars to use in the function. Use those throughout the function then assign those back at the end of the function.

Example:

void addMember(id **list_original, size_t *size_original)
{
    id *list = *list_original;
    int size = *size_original;
 
    size++;
    list = size == 1 ? malloc(sizeof(id)) : realloc(list, size * sizeof(id));
    if (!list) return; // Nothing to do as original values are untouched
    list[size-1].name = malloc (30 * sizeof(char));
    // etc...

    *list_original = list;
    *size_original = size;
}

Another option is to wrap the values in a struct and pass a pointer to that to the function:

typedef struct {
    id *list;
    size_t size;
} list_data;
void addMember(list_data *list)
{
   // If you pass NULL to realloc it acts like malloc
   id *tmp = realloc(list->list, (list->size + 1) * sizeof(id));
   if (!tmp) return;
   list->list = tmp;
   list->list[list->size].name = malloc(30);
   // etc...
   list->size += 1;
}
int main()
{
    list_data list = {NULL, 0};
    addMember(&list);
    // ....
}

Side note: it is bad practice to use the pointer passed to realloc in the result:

list = realloc(list, size * sizeof(id));

The reason is that if realloc fails, the original memory is lost. Use a temp var.

id *temp_list = realloc(list, size * sizeof(id));
if (temp_list) {
    list = temp_list;
    // Continue
}

Upvotes: 0

Related Questions