Un traitement en paramètre d'une fonction

Dans cette partie, nous voulons paramétrer un traitement à effectuer sur tous les éléments contenus dans l’ensemble. Comme exemple, nous prenons une opération de filtre qui à partir d’un ensemble construit un nouvel ensemble.

Filtrer les nombres pairs

La fonction set__filter construit un nouvel ensemble contenant tous les nombres pairs apparaissant dans l’ensemble passé en paramètre. Elle a comme le prototype:

struct set * set__filter(const struct set * s);
  1. Ajouter ce prototype au fichier set.h.
  2. Écrire le code de cette fonction pour une des réalisations (pour simplifier le code, vous pouvez utiliser la fonction set__add pour ajouter des éléments au nouvel ensemble).
  3. Écrire un test fonctionnel pour cette fonction.

Paramétrer la fonction du filtre

L’implémentation actuelle de la fonction de filtre fixe le critère de sélection fait sur la liste. Au lieu de créer autant de fonctions de filtre qu’il existe de traitements, il est préférable de permettre à l’utilisateur du filtre de fournir le critère de sélection à appliquer à chaque élément.

La fonction de sélection à appliquer aux éléments est passée à set_filter grâce au mécanisme des pointeurs de fonction. Un type “pointeur de fonction” représente l’adresse d’une fonction. Des exemples de pointeurs de fonctions sont donnés en annexe.

  1. Donnez le prototype de la fonction de sélection appliquée aux éléments de l’ensemble, puis le nouveau prototype de la fonction set__filter.
  2. Réécrire l’exercice précédent à l’aide de ce nouveau prototype.
  3. Écrire des fonctions de sélection pour d’autres traitements (par exemple, effectuer une copie de l’ensemble).

Compléter les réalisations

Écrire le code de la fonction set__filter pour toutes les réalisations.

Annexe

Exemple de pointeurs de fonctions:

void print(int a) {
  printf("%d\n", a);
}

void printeven(int a) {
  if (a % 2 == 0)
    printf("%d\n", a);
}

// definition de la VARIABLE pf 
// pf est un pointeur sur une fonction de type void(int), c'est à
// dire une fonction qui prend un paramètre de type int et qui ne
// retourne rien
void (*pf)(int);

// initialisation avec l'adresse
// d'une fonction de meme prototype. 
pf = print;

// appel de la fonction a l'adresse contenue
// par la variable pf (i.e. appel de print)
pf(4);

// pf_t est le ``type'' des fonctions prenant un int et de retour
// void
typedef void (*pf_t)(int);

// definition d'une fonction prenant un autre
// fonction en parametre et l'appelant
void apply(pf_t pf, int x) {
  pf(x);
}

// Utilisation de apply
apply(print, 4);
apply(printeven, 3);