Implementare il vettore in C

Implementare il vettore in C

Nel mio precedente articolo, ho spiegato come possiamo creare un array dinamico in C. Ma il mio lettore dice di scrivere un articolo per creare un vettore in C. Fondamentalmente il vettore è un array dinamico che ha la capacità di ridimensionarsi automaticamente quando un elemento aggiungere o rimuovere dal vettore.

Un elemento vettoriale memorizza in modo continuo in modo da poter accedere all'elemento utilizzando l'indice. È fantastico e mi piace anche l'elenco collegato non abbiamo bisogno di allocare la memoria per ogni nodo. All'inizio allochiamo la memoria extra e la regoliamo secondo il requisito.

Quindi veniamo all'argomento e creiamo un semplice vettore. Poiché C non è supportato per il modello e il vettore, quindi qui sto creando un vettore usando la struttura e il puntatore. Questo vettore memorizzerà l'indirizzo dell'elemento usando void * (Puntatore generico, puoi vedere questo articolo). Il vantaggio del puntatore void è che possiamo memorizzare l'indirizzo di qualsiasi tipo di dati.

Implementazione del codice del vettore in C

Innanzitutto, dobbiamo creare una struttura che memorizzi i dati e tenga traccia dei dati archiviati. Sto anche creando qui un'altra struttura per memorizzare il puntatore alla funzione che punta alla funzione vettoriale (perché C non supporta la funzione in una struttura come C++).

//Store and track the stored data
typedef struct sVectorList
{
    void **items;
    int capacity;
    int total;
} sVectorList;

//structure contain the function pointer
typedef struct sVector vector;
struct sVector
{
    sVectorList vectorList;
//function pointers
    int (*pfVectorTotal)(vector *);
    int (*pfVectorResize)(vector *, int);
    int (*pfVectorAdd)(vector *, void *);
    int (*pfVectorSet)(vector *, int, void *);
    void *(*pfVectorGet)(vector *, int);
    int (*pfVectorDelete)(vector *, int);
    int (*pfVectorFree)(vector *);
};

Ora devi creare alcune macro per una migliore leggibilità e allocare inizialmente la memoria. Puoi modificare il valore della macro secondo le tue esigenze.

#define VECTOR_INIT_CAPACITY 6
#define UNDEFINE  -1
#define SUCCESS 0


#define VECTOR_INIT(vec) vector vec;\
 vector_init(&vec)

Inizializzazione del vettore:

In questa funzione, sto inizializzando la capacità del vettore e dei puntatori di funzione con la funzione appropriata.

void vector_init(vector *v)
{
    //init function pointers
    v->pfVectorTotal = vectorTotal;
    v->pfVectorResize = vectorResize;
    v->pfVectorAdd = vectorPushBack;
    v->pfVectorSet = vectorSet;
    v->pfVectorGet = vectorGet;
    v->pfVectorFree = vectorFree;
    v->pfVectorDelete = vectorDelete;
    //initialize the capacity and allocate the memory
    v->vectorList.capacity = VECTOR_INIT_CAPACITY;
    v->vectorList.total = 0;
    v->vectorList.items = malloc(sizeof(void *) * v->vectorList.capacity);

}

Ridimensiona il vettore:

Questa funzione alloca la memoria con una nuova dimensione utilizzando la funzione di libreria realloc e aggiorna il parametro di tracciamento con il nuovo valore. Puoi anche vedere l'articolo , Come allocare memoria dinamica in C.

int vectorResize(vector *v, int capacity)
{
    int  status = UNDEFINE;
    if(v)
    {
        void **items = realloc(v->vectorList.items, sizeof(void *) * capacity);
        if (items)
        {
            v->vectorList.items = items;
            v->vectorList.capacity = capacity;
            status = SUCCESS;
        }
    }
    return status;
}

Funzione Push Back:

Questa funzione inserisce i dati alla fine del vettore. Se non è disponibile memoria sufficiente, la memoria verrà ridimensionata.

int vectorPushBack(vector *v, void *item)
{
    int  status = UNDEFINE;
    if(v)
    {
        if (v->vectorList.capacity == v->vectorList.total)
        {
            status = vectorResize(v, v->vectorList.capacity * 2);
            if(status != UNDEFINE)
            {
                v->vectorList.items[v->vectorList.total++] = item;
            }
        }
        else
        {
            v->vectorList.items[v->vectorList.total++] = item;
            status = SUCCESS;
        }
    }
    return status;
}

Imposta i dati a un determinato indice:

Questa funzione imposta i dati all'indice specificato se l'indice è valido. Se passerai l'indice non valido, non farà nulla.

int vectorSet(vector *v, int index, void *item)
{
    int  status = UNDEFINE;
    if(v)
    {
        if ((index >= 0) && (index < v->vectorList.total))
        {
            v->vectorList.items[index] = item;
            status = SUCCESS;
        }
    }
    return status;
}

Ottieni l'indirizzo dei dati dall'indice dato:

Se l'indice è valido, questa funzione restituirà l'indirizzo dei dati dell'indice specificato. Se l'indice non è valido, restituirà NULL (puntatore null). Devi digitare la memoria secondo i tipi di dati.

void *vectorGet(vector *v, int index)
{
    void *readData = NULL;
    if(v)
    {
        if ((index >= 0) && (index < v->vectorList.total))
        {
            readData = v->vectorList.items[index];
        }
    }
    return readData;
}

Cancella i dati dell'indice dato:

Questa funzione assegna il NULL all'indice dato e sposta tutti gli elementi nel vettore di 1.

int vectorDelete(vector *v, int index)
{
    int  status = UNDEFINE;
    int i = 0;
    if(v)
    {
        if ((index < 0) || (index >= v->vectorList.total))
            return status;

        v->vectorList.items[index] = NULL;

        for (i = index; (i < v->vectorList.total - 1); ++i)
        {
            v->vectorList.items[i] = v->vectorList.items[i + 1];
            v->vectorList.items[i + 1] = NULL;
        }

        v->vectorList.total--;

        if ((v->vectorList.total > 0) && ((v->vectorList.total) == (v->vectorList.capacity / 4)))
        {
            vectorResize(v, v->vectorList.capacity / 2);
        }
        status = SUCCESS;
    }
    return status;
}

Libera la memoria allocata:

Questa funzione dealloca la memoria allocata.

int vectorFree(vector *v)
{
    int  status = UNDEFINE;
    if(v)
    {
        free(v->vectorList.items);
        v->vectorList.items = NULL;
        status = SUCCESS;
    }
    return status;
}

Esempio di codice di un vettore in C:

In questo esempio, sto creando un vettore di stringa usando la funzione pushback. Dopo aver creato il vettore sto visualizzando la stringa memorizzata con lì index. Ho anche impostato la stringa usando l'indice. Dovresti ricordare che l'indirizzo dei dati dovrebbe essere valido e devi preoccuparti del puntatore penzolante. Puoi anche vedere questo articolo "Come evitare il puntatore penzolante".

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


#define VECTOR_INIT_CAPACITY 6
#define UNDEFINE  -1
#define SUCCESS 0


#define VECTOR_INIT(vec) vector vec;\
 vector_init(&vec)

//Store and track the stored data
typedef struct sVectorList
{
    void **items;
    int capacity;
    int total;
} sVectorList;


//structure contain the function pointer
typedef struct sVector vector;
struct sVector
{
    sVectorList vectorList;
//function pointers
    int (*pfVectorTotal)(vector *);
    int (*pfVectorResize)(vector *, int);
    int (*pfVectorAdd)(vector *, void *);
    int (*pfVectorSet)(vector *, int, void *);
    void *(*pfVectorGet)(vector *, int);
    int (*pfVectorDelete)(vector *, int);
    int (*pfVectorFree)(vector *);
};


int vectorTotal(vector *v)
{
    int totalCount = UNDEFINE;
    if(v)
    {
        totalCount = v->vectorList.total;
    }
    return totalCount;
}

int vectorResize(vector *v, int capacity)
{
    int  status = UNDEFINE;
    if(v)
    {
        void **items = realloc(v->vectorList.items, sizeof(void *) * capacity);
        if (items)
        {
            v->vectorList.items = items;
            v->vectorList.capacity = capacity;
            status = SUCCESS;
        }
    }
    return status;
}

int vectorPushBack(vector *v, void *item)
{
    int  status = UNDEFINE;
    if(v)
    {
        if (v->vectorList.capacity == v->vectorList.total)
        {
            status = vectorResize(v, v->vectorList.capacity * 2);
            if(status != UNDEFINE)
            {
                v->vectorList.items[v->vectorList.total++] = item;
            }
        }
        else
        {
            v->vectorList.items[v->vectorList.total++] = item;
            status = SUCCESS;
        }
    }
    return status;
}

int vectorSet(vector *v, int index, void *item)
{
    int  status = UNDEFINE;
    if(v)
    {
        if ((index >= 0) && (index < v->vectorList.total))
        {
            v->vectorList.items[index] = item;
            status = SUCCESS;
        }
    }
    return status;
}

void *vectorGet(vector *v, int index)
{
    void *readData = NULL;
    if(v)
    {
        if ((index >= 0) && (index < v->vectorList.total))
        {
            readData = v->vectorList.items[index];
        }
    }
    return readData;
}

int vectorDelete(vector *v, int index)
{
    int  status = UNDEFINE;
    int i = 0;
    if(v)
    {
        if ((index < 0) || (index >= v->vectorList.total))
            return status;

        v->vectorList.items[index] = NULL;

        for (i = index; (i < v->vectorList.total - 1); ++i)
        {
            v->vectorList.items[i] = v->vectorList.items[i + 1];
            v->vectorList.items[i + 1] = NULL;
        }

        v->vectorList.total--;

        if ((v->vectorList.total > 0) && ((v->vectorList.total) == (v->vectorList.capacity / 4)))
        {
            vectorResize(v, v->vectorList.capacity / 2);
        }
        status = SUCCESS;
    }
    return status;
}

int vectorFree(vector *v)
{
    int  status = UNDEFINE;
    if(v)
    {
        free(v->vectorList.items);
        v->vectorList.items = NULL;
        status = SUCCESS;
    }
    return status;
}


void vector_init(vector *v)
{
    //init function pointers
    v->pfVectorTotal = vectorTotal;
    v->pfVectorResize = vectorResize;
    v->pfVectorAdd = vectorPushBack;
    v->pfVectorSet = vectorSet;
    v->pfVectorGet = vectorGet;
    v->pfVectorFree = vectorFree;
    v->pfVectorDelete = vectorDelete;
    //initialize the capacity and allocate the memory
    v->vectorList.capacity = VECTOR_INIT_CAPACITY;
    v->vectorList.total = 0;
    v->vectorList.items = malloc(sizeof(void *) * v->vectorList.capacity);

}

int main(int argc, char *argv[])
{
    int i =0;

    //init vector
    VECTOR_INIT(v);
    //Add data in vector
    v.pfVectorAdd(&v,"aticleworld.com\n");
    v.pfVectorAdd(&v,"amlendra\n");
    v.pfVectorAdd(&v,"Pooja\n");

    //print the data and type cast it
    for (i = 0; i < v.pfVectorTotal(&v); i++)
    {
        printf("%s", (char*)v.pfVectorGet(&v, i));
    }


    //Set the data at index 0
    v.pfVectorSet(&v,0,"Apoorv\n");

    printf("\n\n\nVector list after changes\n\n\n");

    //print the data and type cast it
    for (i = 0; i < v.pfVectorTotal(&v); i++)
    {
        printf("%s", (char*)v.pfVectorGet(&v, i));
    }


    return 0;
}

Risultato: 

Articoli consigliati per te:

  • Come creare un array dinamico in C?
  • Come accedere all'array 2d in C?
  • Puntatore funzione in c, una guida dettagliata
  • Come utilizzare la struttura del puntatore a funzione in linguaggio c?
  • Puntatore funzione nella struttura.
  • Implementare la propria memoria in C.
  • memmove vs memcpy.
  • Implementare il proprio memcpy in C.
  • Come utilizzare strncpy() e implementare il proprio strncpy().
  • Come passare un array come parametro?
  • Implementare il proprio atoi in C.
  • Come utilizzare la condizione C if-else?
  • Come si usa for loop in C?
  • Dovresti sapere durante l'uso in loop.
  • Operatori con Precedenza e Associatività.
  • Aritmetica del puntatore in C.
  • puntatore vuoto in C.
  • Una breve descrizione del puntatore in C.
  • Puntatori penzolanti, vuoti, nulli e selvaggi
  • Quando e come utilizzare l'array in C?
  • Layout di memoria in C.
  • Gestione dei file in C, tra poche ore.