OldWildWeb Logo

Vettori Dinamici in C

I vettori dinamici in C come nel C++ tramite una libreria


Vettori dinamici in C come nel C++

Tra le varie caratteristiche del C++ vi è il supporto per i vettori dinamici tramite la libreria STD e il template class vector, rispetto gli array tradizionali è possibile modificare dinamicamente la dimensione dei vettori, aggiungere e rimuovere elementi queste funzionalità sono sicuramente molto apprezzate dai programmatori.

In C purtroppo non vi è nessuna libreria standard per gestire array dinamici, in questo articolo vedremo un esempio di una libreria che emula la classe template vector del c++.

int main(int argc, char** argv) {
int i = 0;
VectorGeneric_DataType theVector;
VectorGeneric_Init(&theVector);
for (i = 0; i < 10; i++)
{
theVector.PushBack((void *)&theVector, (void *) &i, sizeof(int));
}
printf("\n\nVector Content");
for (i = 0; i < theVector.size; i++)
{
printf("\n Element[%d] = %d", i, *(int *)theVector.data[i]);
}
theVector.DeleteAt(&theVector, 7, free);
printf("\n\nVector Content After deleting item at position 7");
for (i = 0; i < theVector.size; i++)
{
printf("\n Element[%d] = %d", i, *(int *)theVector.data[i]);
}
return (EXIT_SUCCESS);
}


Output del codice qui sopra:
Vector Content
Element[0] = 0
Element[1] = 1
Element[2] = 2
Element[3] = 3
Element[4] = 4
Element[5] = 5
Element[6] = 6
Element[7] = 7
Element[8] = 8
Element[9] = 9

Vector Content After deleting item at position 7
Element[0] = 0
Element[1] = 1
Element[2] = 2
Element[3] = 3
Element[4] = 4
Element[5] = 5
Element[6] = 6
Element[7] = 8
Element[8] = 9


File "cvector.c"
#include 
#include
#include
#include "cvectors.h"

void VectorGeneric_Init(VectorGeneric_DataType *TheVectorGeneric)
{
TheVectorGeneric->size = 0;
TheVectorGeneric->data = NULL;
TheVectorGeneric->element_size = NULL;
//Functions Pointers
TheVectorGeneric->DeleteAt = (void *)VectorGeneric_DeleteAt;
TheVectorGeneric->Destroy = (void *)VectorGeneric_Destroy;
TheVectorGeneric->PopBack = (void *)VectorGeneric_PopBack;
TheVectorGeneric->PushBack = (void *)VectorGeneric_PushBack;
TheVectorGeneric->SoftDestroy = (void *)VectorGeneric_SoftDestroy;
TheVectorGeneric->SoftPopBack = (void *)VectorGeneric_SoftPopBack;
}

void VectorGeneric_PushBack(VectorGeneric_DataType *TheVectorGeneric, void * TheElementData, int TheElementSize)
{
if (TheVectorGeneric->data != NULL)
{
TheVectorGeneric->data = (void **) realloc(TheVectorGeneric->data, sizeof(void *) * (TheVectorGeneric->size+1));
}
else
{
TheVectorGeneric->data = (void **) malloc (sizeof(void *) * (TheVectorGeneric->size+1));
}
if (TheVectorGeneric->element_size != NULL)
{
TheVectorGeneric->element_size = (int *) realloc (TheVectorGeneric->element_size, sizeof(int) * (TheVectorGeneric->size+1));
}
else
{
TheVectorGeneric->element_size = (int *) malloc (sizeof(int));
}
TheVectorGeneric->data[TheVectorGeneric->size] = (void *) calloc(1, TheElementSize);
memcpy(TheVectorGeneric->data[TheVectorGeneric->size], TheElementData, TheElementSize);
TheVectorGeneric->element_size[TheVectorGeneric->size] = TheElementSize;
TheVectorGeneric->size++;
}

void VectorGeneric_PopBack(VectorGeneric_DataType *TheVector, void (*DeleteElementFunction)(void *TheElementToDelete))
{
DeleteElementFunction((void *) TheVector->data[TheVector->size-1]);
free(TheVector->data[TheVector->size-1]);
if (TheVector->size > 1)
{
TheVector->data = (void **) realloc(TheVector->data, sizeof(void *) * (TheVector->size-1));
TheVector->element_size = (int *) realloc (TheVector->element_size, sizeof(int) * (TheVector->size-1));
}
else
{
free(TheVector->data);
free(TheVector->element_size);
TheVector->data = NULL;
TheVector->element_size = NULL;
}
TheVector->size--;
}

void VectorGeneric_SoftPopBack(VectorGeneric_DataType *TheVector)
{
free(TheVector->data[TheVector->size-1]);
if (TheVector->size > 1)
{
TheVector->data = (void **) realloc(TheVector->data, sizeof(void *) * (TheVector->size-1));
TheVector->element_size = (int *) realloc (TheVector->element_size, sizeof(int) * (TheVector->size-1));
}
else
{
free(TheVector->data);
free(TheVector->element_size);
TheVector->data = NULL;
TheVector->element_size = NULL;
}
TheVector->size--;
}
void VectorGeneric_Destroy(VectorGeneric_DataType *TheVector, void (*DeleteElementFunction)(void *TheElementToDelete))
{
int i;
for (i = 0; i < TheVector->size; i++)
{
DeleteElementFunction((void *) TheVector->data[i]);
free(TheVector->data[i]);
}
free(TheVector->data);
free(TheVector->element_size);
TheVector->data = NULL;
TheVector->element_size = NULL;
TheVector->size = 0;
}
void VectorGeneric_SoftDestroy(VectorGeneric_DataType *TheVector)
{
int i;
for (i = 0; i < TheVector->size; i++)
{
free(TheVector->data[i]);
}
free(TheVector->data);
free(TheVector->element_size);
TheVector->data = NULL;
TheVector->element_size = NULL;
TheVector->size = 0;
}
void VectorGeneric_DeleteAt(VectorGeneric_DataType *TheVector, int index, void (*DeleteElementFunction)(void *TheElementToDelete))
{
int i;
VectorGeneric_DataType TempVector;
VectorGeneric_Init(&TempVector);
for (i = index + 1; i < TheVector->size; i++)
{
VectorGeneric_PushBack(&TempVector, TheVector->data[i], TheVector->element_size[i]);
}
//Permanent delete of the item in the heap
DeleteElementFunction((void *) TheVector->data[index]);
while (TheVector->size > index)
{
VectorGeneric_SoftPopBack(TheVector);
}
for (i = 0; i < TempVector.size; i++)
{
VectorGeneric_PushBack(TheVector, TempVector.data[i], TempVector.element_size[i]);
}
VectorGeneric_SoftDestroy(&TempVector);
}
void VectorString_Init(VectorString_DataType *TheVector)
{
TheVector->size = 0;
TheVector->data = NULL;
TheVector->element_size = NULL;
//Functions Pointers
TheVector->DeleteAt = (void *)VectorString_DeleteAt;
TheVector->Destroy = (void *)VectorString_Destroy;
TheVector->PopBack = (void *)VectorString_PopBack;
TheVector->PushBack = (void *)VectorString_PushBack;
}

void VectorString_PushBack(VectorString_DataType *TheVector, char * TheString, int StringLenght)
{
int i;
if (TheVector->data != NULL)
{
TheVector->data = (char **)realloc(TheVector->data, sizeof(char *) * (TheVector->size+1));
}
else
{
TheVector->data = (char **) malloc (sizeof(char *) * (TheVector->size+1));
}
if (TheVector->element_size != NULL)
{
TheVector->element_size = (int *) realloc (TheVector->element_size, sizeof(int) * (TheVector->size+1));
}
else
{
TheVector->element_size = (int *) malloc (sizeof(int) * 1);
}
TheVector->data[TheVector->size] = (char *) calloc(sizeof(char), StringLenght + 1);
for (i = 0; i < StringLenght; i++ )
{
TheVector->data[TheVector->size][i] = TheString[i];
}
TheVector->element_size[TheVector->size] = i;
TheVector->data[TheVector->size][TheVector->element_size[TheVector->size]] = '\0';
TheVector->size++;
}

void VectorString_PopBack(VectorString_DataType *TheVector)
{
free(TheVector->data[TheVector->size-1]);
if (TheVector->size > 1)
{
TheVector->data = (char **)realloc(TheVector->data, sizeof(char *) * (TheVector->size-1));
TheVector->element_size = (int *) realloc (TheVector->element_size, sizeof(int) * (TheVector->size-1));
}
else
{
free(TheVector->data);
free(TheVector->element_size);
TheVector->data = NULL;
TheVector->element_size = NULL;
}
TheVector->size--;
}

void VectorString_Destroy(VectorString_DataType *TheVector)
{
int i;
for (i = 0; i < TheVector->size; i++)
{
free(TheVector->data[i]);
}
free(TheVector->data);
free(TheVector->element_size);
TheVector->data = NULL;
TheVector->element_size = NULL;
TheVector->size = 0;
}

void VectorString_DeleteAt(VectorString_DataType *TheVector, int index)
{
int i;
VectorString_DataType TempVector;
VectorString_Init(&TempVector);
for (i = index + 1; i < TheVector->size; i++)
{
VectorString_PushBack(&TempVector, TheVector->data[i], TheVector->element_size[i]);
}
while (TheVector->size > index)
{
VectorString_PopBack(TheVector);
}
for (i = 0; i < TempVector.size; i++)
{
VectorString_PushBack(TheVector, TempVector.data[i], TempVector.element_size[i]);
}
VectorString_Destroy(&TempVector);
}


File "cvector.h"

#ifndef CVECTORS_H
#define CVECTORS_H
#ifdef __cplusplus
extern "C" {
#endif
struct VectorString
{
char **data;
int size;
int *element_size;
void (*PushBack)(void *TheVector, char * TheString, int StringLenght);
void (*PopBack)(void *TheVector);
void (*Destroy)(void *TheVector);
void (*DeleteAt)(void *TheVector, int index);
} typedef VectorString_DataType;

struct VectorGeneric
{
void **data;
int size;
int *element_size;
void (*PushBack)(void *TheVectorGeneric, void * TheElementData, int TheElementSize);
void (*PopBack)(void *TheVector, void (*DeleteElement)(void *TheElementToDelete));
void (*SoftPopBack)(void *TheVector);
void (*Destroy)(void *TheVector, void (*DeleteElement)(void *TheElementToDelete));
void (*SoftDestroy)(void *TheVector);
void (*DeleteAt)(void *TheVector, int index, void (*DeleteElement)(void *TheElementToDelete));
} typedef VectorGeneric_DataType;

void VectorString_Init(VectorString_DataType *TheVector);
void VectorString_PushBack(VectorString_DataType *TheVector, char * TheString, int StringLenght);
void VectorString_PopBack(VectorString_DataType *TheVector);
void VectorString_Destroy(VectorString_DataType *TheVector);
void VectorString_DeleteAt(VectorString_DataType *TheVector, int index);
void VectorGeneric_Init(VectorGeneric_DataType *TheVectorGeneric);
void VectorGeneric_PushBack(VectorGeneric_DataType *TheVectorGeneric, void * TheElementData, int TheElementSize);
void VectorGeneric_PopBack(VectorGeneric_DataType *TheVector, void (*DeleteElementFunction)(void *TheElementToDelete));
void VectorGeneric_SoftPopBack(VectorGeneric_DataType *TheVector);
void VectorGeneric_Destroy(VectorGeneric_DataType *TheVector, void (*DeleteElementFunction)(void *TheElementToDelete));
void VectorGeneric_SoftDestroy(VectorGeneric_DataType *TheVector);
void VectorGeneric_DeleteAt(VectorGeneric_DataType *TheVector, int index, void (*DeleteElementFunction)(void *TheElementToDelete));
#ifdef __cplusplus
}
#endif
#endif
/* CVECTORS_H */