Reputation: 358
I have written a small program in which I use a pointer to keep track of array of structures. I have a few questions regarding the same:
1) In main()
, I iterate using the macro "COUNT". How can I iterate using the arr_struct
or arr_struct[i]
in place of COUNT? Is it possible to derive the number of entries in arr_struct
from arr_struct
?
2) Is the following statement OK if I do not wish to assign a value to place
?
(*as)[i].name = strdup("foo");
(*as)[i].place = NULL;
(*as)[i].n = 1234;
3) Do you see any wrong programming practice, bug, or memory (allocation and free) related issues in the following code?
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
typedef struct info_s {
char *name;
char *place;
int n;
} info_t;
#define COUNT 2
static void
get_data (info_t **as)
{
int i = 0;
for (i = 0; i < COUNT; i++) {
info_t *tmp = (info_t *)realloc(*as, (i + 1) * sizeof(info_t));
if (tmp != NULL) {
*as = tmp;
(*as)[i].name = strdup("foo");
(*as)[i].place = strdup("bar");
(*as)[i].n = 1234;
}
}
}
int main (int argc, char** argv)
{
info_t *arr_struct = NULL;
int i;
get_data(&arr_struct);
for(i = 0; i < COUNT; i++) {
printf("[%d].name:%s,\t", i, arr_struct[i].name);
printf("[%d].place:%s,\t", i, arr_struct[i].place);
printf("[%d].n:%d\n", i, arr_struct[i].n);
}
for(i = 0; i < COUNT; i++) {
free(arr_struct[i].name);
free(arr_struct[i].place);
}
free(arr_struct);
return 0;
}
Upvotes: 0
Views: 81
Reputation: 532
Since realloc()
is a too "expensive" function, the standard aproach is as follows.
const int capacity = 100; // for example
static void
get_data (info_t **as)
{
int i = 0;
for (i = 0; i < COUNT; i++) {
info_t *tmp = *as;
if (i % capacity == 0)
tmp = (info_t *)realloc(*as, capacity * (i/capacity + 1) * sizeof(info_t));
if (tmp != NULL) {
*as = tmp;
(*as)[i].name = strdup("foo");
(*as)[i].place = strdup("bar");
(*as)[i].n = 1234;
}
}
}
I apologize for the non-optimal code in this example. I made minimal changes to the source code solely for demonstration.
More accurate example
const int capacity = 100; // for example
static void
get_data (info_t **as)
{
int i = 0;
for (i = 0; i < COUNT; i++) {
if (i % capacity == 0)
info_t *tmp = (info_t *)realloc(*as, capacity * (i/capacity + 1) * sizeof(info_t));
if (tmp != NULL) {
*as = tmp;
}
else {
fprintf(stderr, "Not enough memory\n");
exit(1);
}
}
(*as)[i].name = strdup("foo");
(*as)[i].place = strdup("bar");
(*as)[i].n = 1234;
}
}
Upvotes: 2
Reputation: 6280
1) add an 'end' member to your structure set to Zero normally, add another instance of that structure in get_data, with that member set to -1 and then loop up to it in your main.
2) That will work in get_data but blow up the printf (and your free). You'd have to check for it. Better to always set it to "". If it means something special to be null, it would be clearer from a 'be nice to the programmer' standpoint to add another member. (yes it takes more memory. Your computer has a lot of that.)
3) Looks pretty good to me. I would have forgotten to free the strings. General advice - realloc will work for <1000 items but if you have 100s of k, use a linked list. It will also solve some of the other problems you speak of (of course, you won't have index access, but for this sample you don't demonstrate a need).
good luck!
Upvotes: 2