INFO517-cours10

De Wiki du LAMA (UMR 5127)
Aller à la navigation Aller à la recherche

Séance 10 du Cours-TD de Programmation C.

Deuxième partiel

Le sujet: INFO517-Partiel2.pdf.

Pointeurs sur fonctions

Un exemple qui rassemble un peu tout: on définit un type de pointeur sur les fonctions des entiers vers les entiers. On maintient une liste d'associations option (chaîne) fonction (donnée par un pointeur). Le programme lit ses options et applique les transformations correspondantes, en partant de 0.

<source lang="c">

  1. include <stdio.h>
  2. include <string.h>
  3. include <stdlib.h>

/* Définition du type des transformations:

* pointeur sur une fonction des entiers vers les entiers. */ 

typedef int (*trans) (int) ;

/* Quelques transformations */

int identite (int n) { return n ; }

int succ (int n) { return n+1 ; }

int oppose (int n) { return -n ; }

int moitie (int n) { return n/2 ; }

int doubl (int n) { return 2*n ; }

int carre (int n) { return n*n ; }

/* Application d'une transformation */

void applique (int *n, trans f) { *n = f(*n) ; }

/* Gestion d'une table d'association: option -> transformation */

typedef struct { const char *opt ; trans f ; } assoc ;

/* Une table d'association est un tableau d'éléments du type `assoc', terminé

* par le couple (NULL,NULL). */

trans cherche (const char *opt, assoc table[]) { int i = 0 ; while (table[i].opt != NULL && strcmp(table[i].opt,opt) != 0) ++i ; return table[i].f ; }

/* Programme principal: pour chaque option donnée, on cherche la transformation

* correspondante et on l'applique à n. */

int main (int argc, const char **argv) { int n = 0 ; int i ; trans f ;

/* Table d'association */ assoc options[] = { {"-i", identite}, {"-s", succ}, {"-o", oppose}, {"-m", moitie}, {"-d", doubl}, {"-c", carre}, {NULL, NULL} } ;

for (i=1;i<argc;i++) { if ((f = cherche(argv[i],options)) == NULL) { fprintf(stderr,"Option non reconnue: \"%s\".\n",argv[i]) ; return EXIT_FAILURE ; } applique(&n,f) ; printf("%d\n",n) ; } return EXIT_SUCCESS ; } </source>

Mise en œuvre dans la bibliothèque de gestion de listes

On propose une troisième version du programme de gestion de listes, avec un exemple pour les les chaînes. La principale nouveauté: on utilise les pointeurs sur fonctions pour écrire des fonctions génériques d'action ou de transformation sur les éléments d'une liste.

L'essentiel est dans liste.h/liste.c. On ajoute des types de pointeurs sur fonctions agissant sur les données (action, transformation, comparaison): <source lang="c"> typedef void (*data_action_t) (data_t) ; typedef data_t (*data_trans_t) (data_t) ; typedef int (*data_comp_t) (data_t, data_t) ; </source> On définit des fonctions: <source lang="c"> void liste_applique (data_trans_t f, liste_t *l) ; void liste_agit (data_action_t f, liste_t *l) ; </source> qui en dépendent. De plus, les fonctions sur les listes triées sont paramétrées par une fonction de comparaison: <source lang="c"> void liste_insere_trie (data_comp_t cmp, liste_t *l, data_t t) ; void liste_trie (data_comp_t cmp, liste_t *l) ; </source>

On donne un exemple d'utilisation dans test_ligne.c (avec plus d'options qu'avant, ce qui est facilité par la généricité offerte par les pointeurs sur fonctions): compilez avec

 $ make 

et lancez

 $ ./test_liste -h 

pour voir toutes les options.