King King - 1 month ago 7
C Question

Dynamic array Vector in C

‚óŹ int vectorInsert(Vector * array, int index, Data value);

I am doing

If this can be corrected according to the given statement.

I am calling it using

Vector *vect = initVector();
Data data_array[20];
for(i = 0 ; i < 20 ; i++){
data_array[i].value = (rand() % 20) + 1;
vectorInsert(vect, i, data_array[i]);
}

Answer

First, according to your specifications, max_size should be an unsigned integer, so I changed Vector to reflect this, using size_t. I also changed the related format specifiers from %d to %zu to match this new type.

Your initVector() function needed to allocate memory for a Vector, so that has been added. Furthermore, there was no need to allocate memory for the dynamic array of Data structs here, so v->data is set to NULL. This function should also return the pointer to the newly allocated memory, v, instead of a pointer to the .data field of this Vector, as you originally had.

In the vectorInsert() function, you neglected to check for memory allocation errors, so I added a check after the attempted allocation which returns 0 if there is an error. After inserting the new Data struct, your check to increment .current_size is wrong. First, you need to increment if array->current_size <= index. Next, you need to add one to the .current_size, not set .current_size to one larger than the index value. Also, when printing the inserted value here, you forgot to access the .value field. I think that this may have been due to the confusing name that you used for the Data struct that you passed into vectorInsert(). You call this struct value, so in the previous line we have array->data[index] = value, where you are assigning the struct value to array->data[index]. But in the call to printf() you want to show the value held by the struct value. Choosing better names is always a win! Finally, this function returns 1 on a successful insertion.

I added to your test code to display the contents of vect and vect->data, and also added a Data struct, test_insert, to test insertion into an arbitrary index.

Finally, you need to free memory allocations after all of this, so I added a couple of calls to free().

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    int value;
}Data;

/* Specs say that max_size should be an unsigned integer */
typedef struct{
    size_t max_size; //initialize to 0
    size_t current_size; //initialize to 0
    Data *data;  // array of integers we're storing
} Vector;

/* Modified function */
Vector * initVector(void){
    Vector *v = malloc(sizeof(*v));
    v->max_size=0;
    v->current_size=0;
    v->data = NULL;
    return v;
}

int  vectorInsert(Vector * array, size_t index, Data value)
{
    if(index >= array->max_size)
    {
        array->max_size = index * 2 + 1; 
        printf("Inside Vect max_size is : %zu\n", array->max_size);

        Data *new_array = malloc(sizeof(Data) * array->max_size);

        /* Added check for allocation error */
        if (new_array == NULL)
            return 0;

        if(array->data != NULL)
        {
            memcpy(new_array, array->data, sizeof(Data)*array->current_size);
            free(array->data);
            array->data = NULL;
        }
        array->data = new_array;
    }

    array->data[index] = value;

    printf("Main : %d\n", array->data[index].value);

    /* Modified current_size increment logic */
    if(array->current_size <= index)
    {
        array->current_size += 1;
    }

    /* Successful insertion */
    return 1;
}

int main(void)
{
    size_t i;
    Vector *vect = initVector();
    Data data_array[20];
    Data test_insert = { -5 };      // to test index insertion

    for(i = 0 ; i < 20 ; i++){
        data_array[i].value = (rand() % 20) + 1;
        vectorInsert(vect, i, data_array[i]);
    }

    /* Display results */
    printf("vect->max_size = %zu\n", vect->max_size);
    printf("vect->current_size = %zu\n", vect->current_size);
    printf("vect->data contains:\n");
    for (i = 0; i < vect->current_size; i++)
        printf("%d ", vect->data[i].value);
    putchar('\n');

    /* Insert test_insert at index 5 */
    vectorInsert(vect, 5, test_insert);

    /* Display results */
    printf("vect->max_size = %zu\n", vect->max_size);
    printf("vect->current_size = %zu\n", vect->current_size);
    printf("vect->data contains:\n");
    for (i = 0; i < vect->current_size; i++)
        printf("%d ", vect->data[i].value);
    putchar('\n');

    /* Free memory allocations */
    free(vect->data);
    free(vect);

    return 0;
}

And here is a sample of the results:

vect->max_size = 31
vect->current_size = 20
vect->data contains:
4 7 18 16 14 16 7 13 10 2 3 8 11 20 4 7 1 7 13 17 

vect->max_size = 31
vect->current_size = 20
vect->data contains:
4 7 18 16 14 -5 7 13 10 2 3 8 11 20 4 7 1 7 13 17