Jean-Jacques BOURDIN

Université Paris 8
Dépt. Programmation et Informatique Fondamentale
2, rue de la Liberté
93526 Saint-Denis Cedex
FRANCE


Programmation Impérative
Imperative Programming

Spring 2025


Tous les exercices

Overview

Ch I) Let's try!

Ch II) Easy C

    II.A) Variables, Expressions, Types, Instructions

    II.A) Operators

    II.B) Control Flow

    II.C) Data Structures

    II.D) Compilation

Ch III) C Addresses

    III.A) Déjà vu

    III.B) Arrays

    III.D) Lists

    III.D) Trees

    III.C) Functions' Pointeers

Ch IV) C more than that

    Votre premier partiel.

 

 

 

 


Ch III) Adresses C


    III.A) Principles / Principes, Rappels

A variable is a set of three things: a name, a type and a location.
It is in this location that one can find the value of the variable. The address is known by the operator &.

Une variable est un triplet < nom, type, emplacement>. C'est à cet emplacement que, selon le type, on trouve la valeur. On peut connaître l'emplacement, l'adresse, de la variable "a" en utilisant l'opérateur & :
void voirou1 () {
  int i, j;
  printf("i est en %u, j est en %u\n", (int)&i, (int)&j);
}

One may also set this adress into a new variable, a "pointer". The content of such a variable is available, and the content of the pointed variable can be found with the unary operator *.
On peut aussi mettre cette adresse dans une variable spéciale qui contient des adresses, un pointeur. On peut aussi savoir ce qu'il y a à une certaine adresse avec l'opérateur unaire *.
void voirou () {
  int *pi, *pj;
  int i, j;

  printf("i est en %d, j est en %u\n",(int) &i,(int) &j);
  pi = & i;
  pj = & j;
  i  = 7;
  j  = 9;
  printf("En %u il y a %d\n", (int) pi, * pi);
  printf("En %u il y a %d\n", (int) &j, j);  
}

On peut se servir des adresses pour modifier le contenu d'une variable extérieure.
void iv (int * pa, int * pb) {
   * pa = * pa + * pb;
   * pb = * pa - * pb;
   * pa = * pa - * pb;
}
int main () {
   int a, v;
   a = 5;
   v = 8;
   voirou1();
   voirou();
   printf("a = %d\t v = %d\n",a,v);
   iv (&a, &v);
   printf("a = %d\t v = %d\n",a,v);
}
/* dhcp13.ai.univ-paris8.fr: a.out
a = 5	 v = 8
a = 8	 v = 5
*/

Ici, les variables et leurs adresses :
      nom  adresse contenus
main   a   400     5    puis 13        puis 8
main   v   404     8            puis 5
iv     pa  408     400    
iv     pb  416     404
Amusant, non ?
/* une autre version */
#include <stdio.h>

void nrut (int * px, int * py) {
  * px = * px + * py;
  * py = * px - * py;
  * px = * px - * py;
}
void lookatit (int n) {
  int x, y;
  int * px, * py; /* adresses de int */

  x  = n; 
  y  = 3; 
  px  = & x; 
  py  = & y;
  printf("adresses de x %p et y %p\n",px, py);
  printf("Avant : valeurs de x %d et y %d\n",x, y);
  nrut(px,py);
  printf("Avant : valeurs de x %d et y %d\n",x, y);
}
int main () {
  lookatit(5);
}
/*
adresses de x 0x7ff7b32b7768 et y 0x7ff7b32b7764
Avant : valeurs de x 5 et y 3
Apres : valeurs de x 3 et y 5
*/
Voici un autre exemple, que vous reconnaîtrez aisément :
/* Fait par JJ B en 2010 */

typedef int * pint;

void fct (int nb, int rg, pint a, pint b) {
  if (nb > rg) {
    *a = *a + *b;
    *b = *a - *b;
    fct (nb, rg + 1, a, b);
  }
}
main () {
  int i, n, a, b;

  n = 10;
  for (i = 0; i <= n; i++) {
    a = 1;
    b = 1;
    fct (i, 0, &a, &b);
    printf("%d => %d\n", i, b);
  }
}

 

 

    III.B) Arrays and pointers / Vecteurs et Tableaux

  1. Retour
    What is an array? Nothing else than a pointer.
    Qu'est-ce qu'un tableau ? Un pointeur ! On peut parcourir un tableau, case à case, par un pointeur :
    /* Fait par JJ B */
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct vecteur {
      int nbe;
      float tab [100];
    } vecteur_t;
    
    typedef float * pfloat;
    
    float somv (vecteur_t v) {
      int i;
      float som;
      pfloat p;
      p = v.tab;
      som = 0;
      for (i = 0; i < v.nbe; i++) {
        som = som + *p;
        p ++;
      }
      return som;
    }
    
    On suppose que le vecteur a été défini par ailleurs. Voici une illustration du fonctionnement de cette fonction :
    vecteur_t remplir (int nb) {
    float x, eps;
      vecteur_t vec;
      int i;
    
      vec.nbe = 0;
      if (nb >= 100)
    	return vec;
      vec.nbe = nb;
      x = 1.5;
      eps = 0.173;
      for (i = 0; i < nb; i = i + 1) {
    	vec.tab [i] = x;
    	x = x + eps;
    	if (x > 2.0)
    	  eps = 0.01 - eps;
    	if (x < 0.5)
    	  eps = 0.015 - eps;
      }
    }
    void voirvec (vecteur_t v) {
      int i;
      if (v.nbe  >= 100)
    	return;
      for (i = 0; i < v.nbe; i = i + 1) {
    	printf("vec[%3d] == %f\n",i, v.tab [i]);
      }
    }
    
    void voirvec2 (vecteur_t v) {
      int i;
      float * pf;
      if (v.nbe  >= 100)
         return;
      pf = v.tab;	    
      for (i = 0; i < v.nbe; i = i + 1) {
    	printf("vec[%3d] == %f\n",i, *pf);
            pf++;
      }
    }
    

    Il vous reste à reprendre quelques exercices faits avec des vecteurs, mais cette fois, en utilisant les pointeurs.

    Exemple de convertisseur

    En-tête
    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #define MAXB 30
    #define MAXD 30
    
    typedef unsigned char uchar;
    typedef struct binaire {
      int nbent;
      int nbfrac; /* nombre de chiffres entiers et post virgule */
      //  uchar ent [MAXB];
      //  uchar frac [MAXB];
      uchar *ent;
      uchar *frac;
    } binaire_t;
    typedef struct decimal {
      int nbent;
      int nbfrac; /* nombre de chiffres entiers et post virgule */
      uchar *ent;
      uchar *frac;
    } decimal_t;
    
    Fonction main :
    int main () {
      binaire_t b;
      decimal_t d;
      float deci, bina;
    
    
      deci = 134.125;
      d = nb2dec(deci);
      printf("Pour %f le code est :\n", deci);
      aff_dec(d);
      bina = 110011.11001;
      b = nb2bin(bina);
      printf("Pour %f le code est :\n", bina);
      aff_bin(b);
    }
        
    Transformer un nombre pour le mettre dans la structure :
    
    decimal_t nb2dec (double xx) { /* prend un nombre et le met dans les cases*/
      decimal_t dd;
      int i, nbc, chiffre, nbchif, nbfrac, p10;
      float frac;
      int partieent;
    
      partieent = (int) xx;
      frac = xx - partieent;
      /* combien de chiffres */
      nbchif = 0;
      i = 1;
      while (i <= partieent) {
        i *= 10;
        nbchif++;
      }
      p10 = 10;
      dd.nbent = nbchif;
      dd.ent = malloc(nbchif * sizeof(uchar));
      assert(dd.ent);
      
      for (i=0; i < nbchif; i++) {
        dd.ent[i] = (uchar) (partieent % 10);
        //    printf("partiee %d val %d\n", partieent, dd.ent[i]);
        partieent /= 10;
    
      }
      dd.nbfrac = 10;
      nbfrac = 10; /* 10 chiffres max*/
      dd.frac = malloc(nbfrac * sizeof(uchar));
      assert(dd.ent);
      for (i = 0; i < nbfrac; i++) {
        frac *= 10;
        chiffre = (int) frac;
        frac -= chiffre;
        dd.frac[i] = (uchar) chiffre;
      }
      return dd;
    }
    

    La suite

    void aff_bin (binaire_t bb) {
      int i;
      uchar *ptr;
      
      printf(" voici votre binaire\n");
      ptr = bb.ent + bb.nbent - 1;
      for (i= 0; i < bb.nbent; i++) {
        printf("%2u ", (unsigned int) *ptr--);
      }
      printf(" . ");
      ptr = bb.frac;
      for (i = 0; i < bb.nbfrac; i++) {
        printf("%2u ", (unsigned int) *ptr++);
      }
      printf("\n");
    }
    void aff_dec (decimal_t bb) {
      int i;
      uchar *ptr;
    
      //  printf("nb chiffres %d . %d\n", bb.nbent, bb.nbfrac);
      ptr = bb.ent + bb.nbent - 1;
      for (i = 0; i < bb.nbent ; i++) {
        printf("%2u ", (unsigned int) *ptr--);
      }
      printf(" . ");
      ptr = bb.frac;
      for (i = 0; i < bb.nbfrac; i++) {
        printf("%2u ", (unsigned int) *ptr++);
      }
      printf("\n");
    }
    
    		  
    et maintenant un exemple de convertisseur ;
    
    decimal_t bin2dec(binaire_t bb) {
      int p2, i,j;
      double res, neg;
      
      printf("conversion du binaire au décimal\n");
      aff_bin(bb);
      p2 = 1;
      res = 0.0;
      //  bzero(tmp, (size_t) MAXD, (size_t) 1);
      for (i = 0; i < bb.nbent; i++) {
        res += p2 * bb.ent[i];
        p2 *= 2;
        //    printf("i %d res %f\n", i, res);
      }
      neg = 1.0/ 2.0;
      for (i = 0; i < bb.nbfrac; i++) {
        res += neg * bb.frac[i];
        neg /= 2.0;
      }
      printf("et en float %f\n", res);
      return nb2dec(res);
    }
    
    

        III.C) Listes Chaînées

    1. Lisp like lists
      Listes Lisp

      Hereafter is a function building a list of n numbers. It's written in Scheme, you'll have to translate it.

      Voici une fonction qui construit une liste de n nombres entiers. Elle est en Lisp, il faut donc la transcrire.

      (define (creerl n)
          (if (< n 1)
               ‘(0)
               (cons n (creerl (- n 1)))))
      

    2. Type definition
      Définition des types
      typedef struct cell * liste_t;
      typedef struct cell {
        float obj;
        struct cell * suiv;
      } cell_t;
      

      Here you see that a list is only the address of a structure.

      Où on voit que la liste est en fait uniquement l'adresse d'une structure qui contient une valeur et une liste.

    3. fonctions simples
      int estvide (liste_t l) {
        if (l == (liste_t) 0) {
          return 1;
        }
        return 0;
      }
      int estnonvide (liste_t l) {
        if (l == (liste_t) 0) {
          return 0;
        }
        return 1;
      }
      
    4. La somme des éléments
      float soml (liste_t l) {
        if (estvide(l)) {
          return 0.0;
        }
        return (*l).obj + soml((*l).suiv);
      }
      
    5. Le nombre d‘éléments
      int howmany (liste_t l) {
        if (estvide(l)) {
          return 0;
        }
        return 1 + howmany ((*l).suiv);
      }
      
    6. La construction
      liste_t cons (float nb, liste_t l) {
        liste_t new;
        new = (liste_t) malloc (sizeof(cell_t));
        assert(new);
        (*new).obj = nb;
        (*new).suiv = l;
        return new;
      }
      liste_t creercours (int nb) {
         liste_t l;
         int i;
         float x;
         x = 0.1;
         l = (liste_t) 0;;
         while (nb--) {
            l = cons (x, l);
            x += 0.15;
            if (x > 0.5)
               x -= 0.45;
         }
         return l;
      }
      liste_t creeriter (int nb) {
        liste_t debut;
        int i, j, k, t;
        j = 13;
        k = 21;
        debut = (liste_t) 0;
        for (i = 0; i < nb; i++) {
          debut = cons ((float) j, debut);
          t = (j + k) % 31;
          k = j;
          j = t;
        }
        return debut;
      }
      		  
    7. Trois fonctions d‘affichage
      void affl (liste_t l) {
        if (estvide (l)) {
          printf("\n");
        }
        else {
          printf("%5.2f ", (*l).obj);
          affl ((*l).suiv);
        }
      }
      
      Notons que (*l).nxt s‘écrit aussi l->nxt, la flèche, ici "-" et ">", est un nouvel opérateur qui remplace une écriture un peu longue.
      void affll (liste_t l) {
        if (estvide (l)) {
          printf("\n");
        }
        else {
          printf("%5.2f ", l->obj);
          affll (l->suiv);
        }
      }
      void affw (liste_t l) {
        while (estnonvide (l)) {
          printf("%5.2f ", l->obj);
          l = l->suiv;
        }
        printf("\n");
      }
      
      Des entêtes à inclure :
      #include<stdio.h>
      #include<stdlib.h>
      #include<assert.h>
      
      La fonction main :
      int main () {
        liste_t l;
        int nb, s;
        nb = 10;
        l = creer(nb);
        affw(l);
        s = soml(l);
        printf("Total : %d\n", s);
        s = howmany(l);
        printf("Il y a %d elements\n", s);
      }
      
    8. Liste d‘exercices à faire.
      1. Trouver le plus grand élément.
      2. Afficher les éléments dans l‘ordre inverse.
      3. Mettre les éléments de la liste en ordre inverse. (Attention, il n‘y a pas besoin de malloc pour faire cette fonction).
      4. Fabriquer une liste avec les n premiers entiers (dans l‘ordre décroissant).
      5. Faire la somme des éléments d‘une liste.
      6. Faire la somme des éléments plus petits que 50 d‘une liste.
      7. Faire la moyenne des éléments d‘une liste.
      8. Trouver le médian des éléments d‘une liste.
      9. Mettre au carré tous les éléments d‘une liste passée en paramètre.
      10. Fabriquer une liste des carrés de tous les éléments d‘une autre liste passée en paramètre.
      11. Enlever le premier élément d‘une liste.
      12. Enlever le dernier élément d‘une liste.
      13. Fonction de concaténation de deux listes.
      14. Dans une liste rangée, insérer une cellule à sa place dans l‘ordre.
      15. Faire le tri d‘une liste, par insertion.

      Exemple de solution

      float plusgrandliste (liste_t l, float candidat) {
         if (l) {
            if (l->nb > candidat)
               return plusgrandliste (l->suiv, l->obj);
            return plusgrandliste (l->suiv, candidat);
            
         }
         return candidat; /* il n‘y a plus d‘autre possible*/
      }
      float plusgrandl (liste_t l) {
         if (l)
            return plusgrandliste (l->suiv, l->obj);
         return - FLT_MAX; /* impose d‘avoir inclus float.h */
      }
      
      Ou encore
      float plusgrandliter (liste_t l) {
         float plgd;
         liste_t crt, ptrplgd;
         if (! l)
            return - FLT_MAX; /* il faut avoir inclus limits.h */
         ptrplgd = l;
         plgd = ptrplgd->nb;
         crt = l->nxt;
         while (crt) {
            if (crt->nb > plgd) {
               plgd = crt->nb;
               ptrplgd = crt;
            }
            crt = crt->nxt;
         }
         return plgd;
      }
      

      Insérer dans l'odre croissant.

      void insere2 (liste_t * ele, liste_t * lt) {
        liste_t ptr, nxt;
        if (! (*lt)) {
          (* ele)->suiv = (liste_t) 0;
          *lt = *ele;
          return ;
        }
        if ((*lt)->obj > (*ele)->obj) {
          (*ele)->suiv = *lt;
          *lt = *ele;
          return ;
        }
        ptr = *lt;
        nxt = (*lt)->suiv;
        while (nxt) {
          if (nxt->obj > (*ele)->obj) {
            /* ele doit etre place avant nxt*/
            ptr->suiv = *ele;
            (*ele)->suiv = nxt;
            return ;
          }
          ptr = nxt;
          nxt = nxt->suiv;
        }
        ptr->suiv = *ele;
        (*ele)->suiv = (liste_t) 0;
        return;
      }
      

       

    9. Inversion d‘une liste.
    10. Inversion par la méthode PG/DG.
      (define (re l)
          (ifn (cdr l) l
               (cons (car (re (cdr l)))
                     (re (cons (car l)
                               (re (cdr (re (cdr l)))))))))
      

    11.  

          III.D) Arbres

      "La beauté des arbres est de croître." (qui ?)

      Nous présentons une structure pour des arbres binaires.

      We start by defining some structures.

      /* Arbres binaires tout simplement */
      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      #include <assert.h>
      
      struct noeud {
        int num;
        float val;
        struct noeud * sg;
        struct noeud * sd;
      } noeud_t;
      
      typedef struct noeud * arbre_t;
      
      We‘ll add a new set of values in the tree.
      
      void ajout (arbre_t * a, int v, float x) {
        arbre_t new;
        int rande;
        if (! (*a)) {
      	new = (arbre_t) malloc (sizeof (noeud_t));
      	new->num = v;
      	new->val = x;
      	new->sg = (arbre_t) 0;
      	new->sd = (arbre_t) 0;
      	*a = new;
      	return;
        }
        rande = rand ();
        if (rande & 0x01) {
      	/* on le met à gauche*/
          if (! ((*a)->sg)) {
      	  /* s'il ny a pas de fils gauche */
            (*a)->sg = (arbre_t) malloc (sizeof (noeud_t));
            (*a)->sg->num = v;
            (*a)->sg->val = x;
            (*a)->sg->sg = (arbre_t) 0;
            (*a)->sg->sd = (arbre_t) 0;
            return;
          }
          ajout(&((*a)->sg), v, x);
      	return;
        }
        /* on le met donc a droite*/
        if (! ((*a)->sd)) {
      	/* s'il ny a pas de fils droit */
          (*a)->sd = (arbre_t) malloc (sizeof (noeud_t));
          (*a)->sd->num = v;
          (*a)->sd->val = x;
          (*a)->sd->sg = (arbre_t) 0;
          (*a)->sd->sd = (arbre_t) 0;
          return;
        }
        ajout(&((*a)->sd), v, x);
        return;
      }
      /*
      To create the tree, you add, one after the other, the values in the
      tree.*/
      arbre_t creation (int n) {
        arbre_t a;
        float x, y;
        x = 1.5;
        y = 0.21;
        a = (arbre_t) 0;
        srand(time(NULL));
        while (n--) {
      	ajout (&a, n, x);
      	x += y;
      	y += 0.06;
      	if (x > 3.0 || x < -2.0) {
      	  y = - y;
      	}
        }
        return a;
      }
      
      It is also possible to show the tree created:
      void afficharbre (arbre_t a) {
        if (a) {
      	afficharbre (a->sg);
      	printf("%d %3.2f ", a->num, a->val);
      	afficharbre (a->sd);
        }
      }
      
      int appartient (int nu, arbre_t a) {
        if (! a)
          return 0;
        if (a->num == nu)
          return 1;
        if (appartient (nu, a->sd))
          return 1;
        return appartient (nu, a->sg);
      }
      
      Vous pouvez aussi :
      • Trouver le plus grand val dans un arbre_t.
      • Trouver le second plus petit val dans un arbre.
      • Compter le nombre de noeuds de l‘arbre.
      • Compter le nombre de noeuds dont le champ val est supérieur à une valeur donnée.
      • Compter le nombre de feuilles de l‘arbre (une feuille est un noeud qui n‘a aucun successeur).
      • Renvoyer la profondeur d‘un noeud de l‘arbre. La profondeur est le nombre de générations entre la racine de l‘arbre et la cellule cherchée. La racine est à la profondeur 0, ses successeurs directs à la profondeur 1, etc.
      • Renvoyer la profondeur maximale de l‘arbre.
      • int main () {
          int n;
          arbre_t a, b;
          float x;
        
          /*
          srand(time(NULL));
          */
          n = 20;
          a = creation (n);
          printf("\n Vois \n");
          afficharbre (a);
          printf("\n\n");
          x = 0.72;
          printf("%f dedans %s\n", x, appartient(x,a) ? "Oui" : "Non");
        }
              
        Oh, il ne le trouve pas :
              0.720000 dedans Non
        
        Il faut donc faire une approximation :
        int fappartient (arbre_t a, float x) {
          if (! a)
            return 0;
          if (fabs(a->val - x) < 0.0001)
            return 1;
          return fappartient(a->sg, x) || fappartient (a->sd, x);
        }
        
        int main () {
          int n;
          arbre_t a, b;
          float x;
        
          /*
          srand(time(NULL));
          */
          n = 20;
          a = creation (n);
          printf("\n Vois \n");
          afficharbre (a);
          x = 0.72;
          printf("methode 1\t %f dedans %s\n", x, appartient(a,x) ? "Oui" : "Non");
          printf("methode 2\t%f dedans %s\n", x, fappartient(a,x) ? "OUI" : "NON");
        }
        
        Cette fois :
        methode 1      0.720000 dedans Non
        methode 2      0.720000 dedans OUI
            
        Arbres binaires de recherche
        Binary search tree
        The structure is the same but two conditions are respected:
        for a node with value n, every value in its left part is lower than n
        and every value in its right part is greater or equal than n.
        Here after is a function that build a BST.
        C‘est la même structure mais elle respecte deux conditions : pour tout sommet de valeur n, tous ses descendants à gauche ont une valeur inférieure à n et tous ses descendants à droite one une valeur supérieure ou égale à n.
        Voici la fonction de création d'un tel arbre :
        arbre ajout (arbre a, int v, float x) {
          arbre new;
          if (! a) {
        	new = (arbre) malloc (sizeof (noeud_t));
        	new->num = v;
        	new->val = x;
        	new->fg = (arbre) 0;
        	new->fd = (arbre) 0;
        	return new;
          }
          if (x < a->val) {
        	/* on le met à gauche*/
        	if (! (a->fg)) {
        	  /* s‘il ny a pas de fils gauche */
        	  a->fg = (arbre) malloc (sizeof (noeud_t));
        	  a->fg->num = v;
        	  a->fg->val = x;
        	  a->fg->fg = (arbre) 0;
        	  a->fg->fd = (arbre) 0;
        	  return a;
        	}
        	a->fg = ajout(a->fg, v, x);
        	return a;
          }
          /* on le met donc a droite*/
          if (! (a->fd)) {
        	/* s‘il ny a pas de fils droit */
        	a->fd = (arbre) malloc (sizeof (noeud_t));
        	a->fd->num = v;
        	a->fd->val = x;
        	a->fd->fg = (arbre) 0;
        	a->fd->fd = (arbre) 0;
        	return a;
          }
          a->fd = ajout(a->fd, v, x);
          return a;
        }
        arbre creation (int n) {
          arbre a;
          float x, y;
          x = 1.5;
          y = 0.21;
          a = (arbre) 0;
          while (n--) {
        	a = ajout (a, n, x);
        	x += y;
        	y += 0.06;
        	if (x > 3.0 || x < -2.0) {
        	  y = - y;
        	}
          }
          return a;
        }
        
        Il vous reste à faire la nouvelle fonction d‘appartenance d‘une valeur (à virgule) dans cet arbre.
        int appartient (arbre a, float x) {
          if (! a)
        	return 0;
          if (a->val == x)
        	return 1;
          if (a->val > x)
        	return appartient (a->sg, x);
          return appartient (a->sd, x);
        }
        int appartientf (arbre a, float x) {
          if (! a)
        	return 0;
          if (fabsf(a->val - x) < 0.0001)
        	return 1;
          if (a->val > x)
        	return appartientf (a->sg, x);
          return appartientf (a->sd, x);
        }
        
        Puis une fonction qui compte le nombre d‘occurences d‘une valeur à virgule dans cet arbre.
        Puis une fonction qui affiche toutes les valeurs (val) dans l‘ordre croissant.
        Puis une fonction qui affiche toutes les valeurs (val) dans l‘ordre décroissant.
        Puis une fonction qui renvoie le nombre de sommets de l‘arbre.

            III.C) Pointeurs de fonctions

        D‘abord une déclaration de type.
        typedef void (* ptrfct) ();
        

        Ensuite les fonctions
        void fcta () {
          printf(" a ");
        }
        void fctb () {
          printf(" b ");
        }
        

        void g (void (* fct) ()) {
          printf("g appelle :");
          fct();
          printf("\n");
        }
        void gg (ptrfct f) {
          printf("gg appelle :");
          f();
          printf("\n");
        }
        void fcttest () {
          g(fcta);
          g(fctb);
          gg(fcta);
          gg(fctb);
        }
        

        int menu () {
          int n;
        
          n = 0;
          while (!n) {
        	printf("Choisissez entre la fonction a (tapez 1)\n");
        	printf("et la fonction b (tapez 2) :\n");
        	scanf("%d",&n);
        	if (n==1 || n==2)
        	  break;
            n = 0;
          }
          return n-1; /* Notons le n - 1 */
        }
        

        void main () {
          int n;
          ptrfct tf [] = {fcta, fctb};
        
          fcttest ();
          n = menu();
          tf[n]();
          for (n=0; n < 2; n++)
            gg(tf[n]);
        }
        

        Voici ce travail à peine modifié pour que les fonctions fcta et fctb reçoivent un argument qui sera affiché aussi.
        typedef void (* ptrfct) (int);
        
        void fcta (int a) {
          printf("Fonction 1: ");
          printf("%d\n",a);
        }
        
        void fctb (int a) {
          printf("Fonction 2: ");
          printf("%d\n",a);
        }
        
        void g (void (* fct) (), int n) {
          printf("g appelle :");
          fct(n);
          printf("\n");
        }
        
        void gg (ptrfct f, int n) {
          printf("gg appelle :");
          f(n);
          printf("\n");
        }
        
        int menu () {
          int n;
        
          n = 0;
          while (!n)
            {
              printf("Choisissez entre la fonction a (tapez 1)\n");
              printf("et la fonction b (tapez 2) :\n");
              scanf("%d",&n);
              if (n==1 || n==2)
        	break;
              n = 0;
            }
          return n-1;
        }
        
        int main ()
        {
          int n, m;
          ptrfct tf [] = {fcta, fctb};
        
          m = 10;
          n = menu();
          g(tf[n], m);
          gg(tf[n], m);
        }
        

        --->

    Dernière mise à jour le 25/3/2025 11h00