Originally Posted by
mushy
or would i have to do new person[100] then use person[0] in which case that would be very wastefull ??
If you have no idea how many persons there are going to be, then that will be a problematic method, because as you say there is a good chance the array will be either too big, or worse, too small.
You want to implement a dynamic array using realloc(). The simplest way is to just do this:
Code:
person *array = malloc(sizeof(person)); // one element;
// expand to 2 elements
array = realloc(array, sizeof(person)*2));
However, this means keeping track of the size of the array, and doing more manual allocation for the name and pword pointers. Also, resizing one element at a time is inefficient. So here's an example of a dynamic array "class" in C:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
char *pword;
} person;
typedef struct {
person *e; // "e" is for elements
int size;
int last;
} dray;
person *dray_add (dray*, char*, char*, int);
void dray_grow (dray*, int);
void dray_init (dray*);
void dray_fpop (dray*);
int main(int argc, const char *argv[]) {
char *names[] = { "MK27", "Bob", "unknown" },
*pwds[] = { "uang2Wei", "oCoo0Ju8", "ze4uap0E"};
dray eg;
int i;
dray_init(&eg);
/* populate */
dray_grow(&eg, 3);
for (i=0;i<3;i++)
dray_add(&eg,names[i],pwds[i],0);
/* add another one */
dray_add(&eg,"new","aetel2A8",1);
/* verify */
for (i=0;i<eg.size;i++)
printf("%10s %8s\n",eg.e[i].name,eg.e[i].pword);
/* clean-up */
for (i=0;i<eg.size;i++) dray_fpop(&eg);
free(eg.e);
return 0;
}
person *dray_add (dray *dr, char *name, char *pword, int resize) {
person *cur;
if (resize) dray_grow(dr, 1);
dr->last += 1;
cur = dr->e + dr->last;
cur->name = malloc(strlen(name)+1);
cur->pword = malloc(strlen(pword)+1);
strcpy(cur->name,name);
strcpy(cur->pword,pword);
return cur; /* unused in this example program */
}
void dray_grow (dray *dr, int growby) {
person *tmp = realloc(dr->e, (dr->size+growby)*sizeof(person));
if (!tmp) {
puts("OUT OF MEMORY!!!!!!");
return;
}
dr->e = tmp;
dr->size += growby;
tmp = dr->e + dr->size -1;
tmp->name = NULL;
tmp->pword = NULL;
}
void dray_init (dray *dr) {
dr->size = 0;
dr->last = -1;
dr->e = malloc(0); // so e pointer is a valid address!
}
void dray_fpop (dray *dr) {
person *p = dr->e + dr->last;
if (p->name) free(p->name);
if (p->pword) free(p->pword);
(dr->last)--;
}
Some notes about this:
Realloc() is an "expensive" operation, meaning it takes a lot of processor time, so you should avoid resizing by one element at a time if you can. That is the purpose of the dray_grow() -- since in the example program we know that there will be at least 3 people, we initially grow the array to that size and then fill it with dray_add(). Dray_add() has a final argument to indicate whether the array needs to grow, or if it has already been sized up. Notice that parameter is in red: it's zero when you don't need more space and non-zero when you do.
Dray_fpop() is for convenience. Notice it does not decrease the size of the array, it just frees internal pointers for the last struct (blanking it out). The array itself must be free separately, once all the stucts are blanked.