Reputation: 89
I've been trying for hours to get this function to work correctly. Here's the assignment:
Add: Request the part name, price, and quantity. Save the information to a dynamically allocated array of structs. You may allocate space for up to 3 structs at a time. You will need to create more memory dynamically as needed. Use this struct (you may use typedef if you want to):
So far the code I have is
typedef struct {
char* name;
float price;
int quantity;
}part;
void add(part *item, int *part_count)
{
//char temp[100];
if (!item){
item = malloc(sizeof(part)*3);
}
else{
item = realloc(item, sizeof(part) * ((*part_count*3) + 1));
}
item[*part_count].name = malloc(sizeof(char)*64); // max of 64 characters
printf("Please enter item name: \n");
//fgets(temp, strlen(temp), stdin);
//sscanf(temp, "%s", item[*part_count].name);
scanf("%64s", item[*part_count].name);
printf("Please enter item price: \n");
//fgets(temp, strlen(temp), stdin);
//sscanf(temp, "%f", &item[*part_count].price);
scanf("%f", &item[*part_count].price);
printf("Please enter item quantity: \n");
//fgets(temp, strlen(temp), stdin);
//sscanf(temp, "%d", &item[*part_count].quantity);
scanf("%d", &item[*part_count].quantity);
*part_count = *part_count+ 1;
}
I had attempted to take the input with fgets()
and sscanf()
but using that code it never allows the user to input data and then ends the function.
I believe the problem resides with my allocation of memory as I am getting segmentation faults when I try to do anything with the array such as print out the contents.
Upvotes: 0
Views: 1445
Reputation: 58578
Your function has an impossible interface. It accepts a part *
pointer. This pointer comes into the function by value. Inside the function you assign to it, from the malloc
or realloc
call. But the caller will not see this updated value. When the function returns, the memory you allocated has leaked, and the caller has the original pointer value (probably null).
Also, it is better to encapsulate dynamic arrays with a structure. You have this "part count" variable that is just loose on its own which has to be passed everywhere together with the array to keep track of its size. How about packing them together:
typedef struct part_list {
struct part *part;
int count;
} part_list;
Now have a function to initialize the empty part list. This must be called by everyone who wants to use the other part_list
functions.
void part_list_init(part_list *pl)
{
pl->part = 0;
pl->count = 0;
}
Then write your function to add parts.
int part_list_add(part_list *pl)
{
part_list *p;
int index = pl->count++; /* increment count, keep old value */
/* realloc accepts a null pointer and then behaves like malloc */
p = realloc(pl->part, sizeof *pl->part * pl->count);
if (p == 0)
return 0; /* failed to allocate/extend array */
p1->part = p;
if ((pl->part[index].name = malloc(64)) == 0) {
pl->count = index; /* roll back the count: we didn't really allocate this part */
return 0;
}
/* your code, updated with pl-> access */
printf("Please enter item name: \n");
scanf("%63s", pl->part[index].name); /* 63s not 64s!!! One byte for NUL char! */
printf("Please enter item price: \n");
scanf("%f", &pl->part[index].price); /* check the return value of scanf!!! */
printf("Please enter item quantity: \n");
scanf("%d", &pl->part[index].quantity);
return 1; /* 1 means success */
}
Upvotes: 1
Reputation: 49803
Presumably, the first time you call add(), item will be NULL, and you'll do its initial allocation; subsequent calls realloc so that the array is 3 times the size needed (which I don't think is what you really want).
But the argument that matches up to item doesn't get changed by the call to add(), so it stays NULL, and every call to add() acts as if it is the initial call, allocating space for 3 structs (which will be a problem when you get to adding the 4th struct).
You could make item a **part, and use *part wherever you currently use part, so that the new value of the pointer gets retained (you'd pass the address of a *part as the argument). Or use the new value of item as the return value of the function, which is a bit cleaner IMHO. (This is where reference parameters come in handy, but C doesn't have such things.)
Upvotes: 1