Filippo Calabrese Filippo Calabrese -4 years ago 35
C Question

Simulating a List with array

Good morning!
I must handle a struct array (global variable) that simulates a list. In practice, every time I call a method, I have to increase the size of the array 1 and insert it into the new struct.

Since the array size is static, my idea is to use pointers like this:


  1. The struct array is declared as a pointer to a second struct array.

  2. Each time I call the increaseSize () method, the content of the old array is copied to a new n + 1 array.

  3. The global array pointer is updated to point to a new array



In theory, the solution seems easy ... but I'm a noob of c. Where is that wrong?

struct task {
char title[50];
int execution;
int priority;
};

struct task tasks = *p;


int main() {
//he will call the increaseSize() somewhere...
}

void increaseSize(){

int dimension = (sizeof(*p) / sizeof(struct task));

struct task newTasks[dimension+1];

for(int i=0; i<dimension; i++){

newTasks[i] = *(p+i);

}

free(&p);

p = newTasks;
}

Answer Source

You mix up quite a lot here!

int dimension = (sizeof(*p) / sizeof(struct task));

p is a pointer, *p points to a struct task, so sizeof(*p) will be equal to sizeof(struct task), and dimension always will be 1...

You cannot use sizeof in this situation. You will have to store the size (number of elements) in a separate variable.

struct task newTasks[dimension+1];

This will create a new array, yes – but on the stack. This means that the array will be cleaned up again as soon as you leave your function.

What you need is creating the array on the heap. You need to use malloc function for (or calloc or realloc).

Additionally, I recomment not increasing the array by 1, but rather duplicating its size. You need to store the number of elements contained in then, too, though.

Putting all together:

struct task* p;
size_t count;
size_t capacity;

void initialize()
{
    count = 0;
    capacity = 16;
    p = (struct task*) malloc(capacity * sizeof(struct task));
    if(!p)
        // malloc failed, appropriate error handling!
}

void increase()
{
    size_t c = capacity * 2;
    // realloc is very convenient here:
    // if allocation is successful, it copies the old values
    // to the new location and frees the old memory, so nothing
    // so nothing to worry about except for allocation failure
    struct task* pp = realloc(p, c * sizeof(struct task));
    if(pp)
    {
        p = pp;
        capacity = c;
    }
    // else: apprpriate error handling
}

Finally, as completion:

void push_back(struct task t)
{
    if(count == capacity)
        increase();
    p[count++] = t;
}

Removing elements is left to you – you'd have to copy the subsequent elements all to one position less and then decrease count.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download