Reputation:
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;
#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
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