« INFO517-cours10 » : différence entre les versions
(pointeurs sur fonctions) |
|||
(5 versions intermédiaires par le même utilisateur non affichées) | |||
Ligne 7 : | Ligne 7 : | ||
== Pointeurs sur fonctions == |
== Pointeurs sur fonctions == |
||
Un exemple qui rassemble un peu tout: |
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) <math>\rightarrow</math> fonction (donnée par un pointeur). Le programme lit ses |
|||
options et applique les transformations correspondantes, en partant de 0. |
|||
<source lang="c"> |
<source lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <string.h> |
|||
#include <stdlib.h> |
|||
/* Définition du type des transformations: |
/* Définition du type des transformations: |
||
Ligne 17 : | Ligne 23 : | ||
/* Quelques transformations */ |
/* Quelques transformations */ |
||
int identite (int n) |
|||
{ |
|||
return n ; |
|||
} |
|||
int succ (int n) |
int succ (int n) |
||
Ligne 76 : | Ligne 87 : | ||
/* Table d'association */ |
/* Table d'association */ |
||
assoc options[] = { |
assoc options[] = { |
||
"- |
{"-i", identite}, |
||
"- |
{"-s", succ}, |
||
"- |
{"-o", oppose}, |
||
"- |
{"-m", moitie}, |
||
"- |
{"-d", doubl}, |
||
{"-c", carre}, |
|||
{NULL, NULL} |
|||
} ; |
} ; |
||
int nb_options = 5 ; |
|||
for (i=1;i<argc;i++) { |
for (i=1;i<argc;i++) { |
||
if ((f = cherche(argv[i],options |
if ((f = cherche(argv[i],options)) == NULL) { |
||
fprintf(stderr,"Option non reconnue: \"%s\".\n",argv[i]) ; |
fprintf(stderr,"Option non reconnue: \"%s\".\n",argv[i]) ; |
||
return EXIT_FAILURE ; |
return EXIT_FAILURE ; |
||
Ligne 94 : | Ligne 105 : | ||
} |
} |
||
return EXIT_SUCCESS ; |
return EXIT_SUCCESS ; |
||
} |
} |
||
</source> |
|||
== Mise en œuvre dans la bibliothèque de gestion de listes == |
|||
On propose |
|||
[http://www.lama.univ-savoie.fr/~vaux/ens/liste-v3.tar.gz 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 <tt>liste.h</tt>/<tt>liste.c</tt>. 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> |
</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 <tt>test_ligne.c</tt> (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. |
Dernière version du 15 décembre 2008 à 14:11
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">
- include <stdio.h>
- include <string.h>
- 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.