A simple vector-like struct in C
Il existe en C++ une classe vector. Cette classe permet de stocker des éléments de n'importe quel type.
A l'inverse des vecteurs en mathématiques, les vecteurs en langage de programmation sont simplement des tableaux d'éléments.
Ils permettent de ne plus avoir à se soucier de la gestion de la mémoire, et cette classe dispose de nombreuse méthodes pour manipuler les éléments stockés.
Afin de rendre nos codes plus propres, nous avons décidé d'adapter ces fonctions en C. Je vous propose donc de faire un tour rapide sur les fonctions à disposition avec des exemples simples.
Vous pouvez bien sûr créer vos propres fonctions et, pourquoi pas, les proposer au reste de la communauté.
Cette librairie permet seulement d'enregistrer des pointeurs. Utile pour un tableau de structure par exemple.
Pourquoi ne pas l'utiliser pour lemin ?
La fonction ci-dessous permet de créer un nouveau vecteur. En dessous du prototype sont présentés ses paramètres ainsi que son utilisation.
t_vector *new_vector(size_t elt_size, void (*_delete)(void *))
Prend 2 paramètres :
- la taille de la donnée (ex:
sizeof(t_muffin)
) - une fonction destructrice.
Exemple d'utilisation:
typedef struct s_exemple
{
char *nom;
} t_exemple;
void fonction_qui_casse_tout(t_exemple *ex)
{
free(ex->nom);
free(ex);
}
void affiche_nom(t_exemple *e)
{
ft_putstr(e->nom);
}
int main()
{
t_vector *vector;
t_exemple *ex;
ex = (t_exemple *)malloc(sizeof(ex));
ex->nom = "Super Muffin";
vector = new_vector(sizeof(ex), &fonction_qui_casse_tout);
vector->push(ex, vector);
ft_putstr("Je suis un ");
vector->map(vector, &affiche_nom);
return (1);
}
Cet exemple stocke
ex
dans le vecteur et applique la fonctionaffiche_nom
à tous les éléments du vecteur. On obtiendra donc:$> Je suis un Super Muffin
Dans les descriptions suivantes, la première ligne correspond au prototype de la fonction (pour les curieux), la suivante correspond à son utilisation.
Nous devrons passer la référence du pointeur dans chaque fonction, ce qui n'est pas forcément beau mais est le seul moyen d'utilisation.
Retourne un booléen: 1 si le vecteur est NULL
, 0 si des éléments sont à l'intérieur.
int vector_is_empty(t_vector *self);
self->empty(self);
Vous n'aurez à utiliser cette fonction que dans de rare cas.
Retourne le nombre d'éléments stockés dans le vecteur.
size_t vector_size(t_vector *self);
self->size(self);
Retourne la capacité de stockage du vecteur.
size_t vector_capacity(t_vector *self);
self->v_capacity(self);
Vous n'aurez à utiliser cette fonction que dans de rare cas.
Intervertit deux éléments du vecteur.
void vector_swap(t_vector *self, int index_1, int index_2);
self->swap(self, 1, 2);
1 devient donc 2, et 2 devient 1.
Copie un élément du vecteur dans le pointeur à remplir elem
, en partant de la fin.
void vector_pop(void *elem, t_vector *self);
self->pop(ptr, self);
Correspond à la méthode LIFO (Last In First Out)
Copie un élément du vecteur dans le pointeur à remplir elem
, en partant du début.
void vector_pop_front(void *elem, t_vector *self);
self->pop_front(ptr, self);
Correspond à la méthode FIFO (First In First Out)
Stocke l'élément elem
en dernière position du vecteur.
int vector_push(void *elem, t_vector *self);
self->push(ptr, self);
Renvoie 0 en cas d'erreur, 1 si tout va bien.
Stocke l'élément elem
en première position du vecteur.
int vector_push_front(void *elem, t_vector *self);
self->push_front(ptr, self);
Les anciens éléments seront donc décalés sur la droite !
Retourne une copie de l'élément présent dans le vecteur à l'index donné.
void *vector_at(t_vector *self, int request);
self->at(self, 5);
Retourne le premier élément du vecteur.
void *vector_front(t_vector *self);
self->front(self);
Toute modification sera enregistrée dans le vecteur.
Retourne le dernier élément du vecteur.
void *vector_back(t_vector *self);
self->back(self);
Toute modification sera enregistrée dans le vecteur.
Retourne l'élément du vecteur à l'index donné.
void *vector_data(t_vector *self, int request);
self->data(self, 5);
À l'inverse de
at()
,data()
permet d'enregistrer dans le vecteur toutes les modifications faites sur le pointeur de retour.
Retourne chaque élément du vecteur (avec un appel en boucle). La mémoire du vecteur sera affectée.
void *c_vector_each(t_vector *self);
while ((ptr = self->each(self)))
do_stuff(ptr);
Notez que vous n'avez pas besoin de compteur,
NULL
sera renvoyé une fois le vecteur parcouru.
Applique une fonction sur chaque élément du vecteur.
void c_vector_map(t_vector *self, void (*fct)(void *elt));
self->map(self, &affiche_nom);
Un seul appel à la fonction est nécessaire.
Supprime un élément à un index donné.
int c_vector_remove(size_t i, t_vector *self);
self->remove(5, self);
Tous les éléments à droite seront décalés vers la gauche.
Si jamais vous êtes arrivés là par hasard, le lien vers la librairie : c_vector
Cheers & Octocats !