C pointeurs/Pointeurs de fonctions

Leçons de niveau 14
Une page de Wikiversité, la communauté pédagogique libre.
Début de la boite de navigation du chapitre
Pointeurs de fonctions
Icône de la faculté
Chapitre no 2
Leçon : C pointeurs
Chap. préc. :Pointeurs de fichiers
Chap. suiv. :Tableau de pointeurs de fonctions
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « C pointeurs : Pointeurs de fonctions
C pointeurs/Pointeurs de fonctions
 », n'a pu être restituée correctement ci-dessus.


Introduction[modifier | modifier le wikicode]

  • En langage C, le nom d'une fonction est un pointeur.
  • On peut l’utiliser comme argument dans l'appel d'une fonction.
  • Exemple : G_plot(f); (f(x) étant une fonction)


Un pointeur de fonction doit avoir le même prototype que la fonction pointée.

  • Pour la fonction f(x) :
  
double f     (double x)            {return( pow(x,2.));}
double (*P_f)(double x)


  • Pour la fonction g(x,y) :
double g     (double x,double y)   {return(x*y;}
double (*P_g)(double x,double y)


Pour appeler la fonction, nous utiliserons cette méthode :

  • Pour la fonction f(x) :
((*P_f)(a)) /* corresponds à un appel de fonction de forme f(a). */


  • Pour la fonction g(x,y) :
((*P_g)(a,b)) /* corresponds à un appel de fonction de forme g(a,b). */


Remarque :

  • f et g sont des pointeurs
  • f() et g() sont des fonctions.
  • double (*P_f)(double x) c’est une déclaration de pointeur de fonction.
  • P_f c’est le pointeur.
  • ((*P_f)()) ou (*P_f)() c’est un appel à une fonction.


Exemples graphiques (avec Gnuplot)[modifier | modifier le wikicode]

Dessiner deux fonctions successivement[modifier | modifier le wikicode]

  • La fonction Gplt() dessine f(x) et g(x).
/* ------------------------------ */
/* Save as c01.c                  */
/* ------------------------------ */
#include    <stdio.h>
#include     <math.h>

/* ------------------------------ */
double f(double x)  {return(  pow(x,2.));}
double g(double x)  {return(2.0*x + 3.0);}

/* ------------------------------ */
void G_plt(
double (*P_f)(double x)
)
{
FILE  *fp = fopen("data","w");
double  a = -5.0;

 for(; a <= 5.0; a += 0.3)
   fprintf(fp," %6.3f  %6.3f\n",a,((*P_f)(a)));
 fclose(fp);
}

/* ------------------------------ */
int main(void)
{
 printf(" Type: plot \"data\" ");
    G_plt(f);
 getchar();

 printf(" Type: plot \"data\" ");
    G_plt(g);

 printf("\n\n Press return to continue.\n");
 getchar();

 return 0;
}


Dessiner deux fonctions successivement (2)[modifier | modifier le wikicode]

La fonction G_plot() dessine la fonction (data) et la chaîne de caractères.


/* ------------------------------ */
/* Save as c02.c                  */
/* ------------------------------ */
#include    <stdio.h>
#include     <math.h>

/* ------------------------------ */
double f(double x){return(cos(x));}
char   feq[] = "cos(x)";

/* ------------------------------ */
double g(double x){return(sin(x));}
char   geq[] = "sin(x)";

/* ------------------------------ */
int G_plot(
double (*P_f)(double x),
char   Feq[])
{
FILE *fp;
double a = -5.0;

 fp = fopen("data","w");
 for(; a <= 5.0; a+=.2)
   fprintf(fp," %6.3f %6.3f\n",a,((*P_f)(a)));
 fclose(fp);

 fp = fopen("a_main.plt","w");
 fprintf(fp,"# Gnuplot file : load \"a_main.plt\" \n"
            " set zeroaxis\n"
            " plot \"data\",\\\n"
            " %s\n"
            " reset",Feq);
 fclose(fp);

return 0;
}

/* ------------------------------ */
int main(void)
{
 printf(" load \"a_main.plt\" with gnuplot ");
    G_plot(f,feq);
 getchar();

 printf(" load \"a_main.plt\" with gnuplot ");
    G_plot(g,geq);

 printf("\n\n Press return to continue.\n");
 getchar();

 return 0;
}

Résultat après le premier appel de G_plot():

 # Gnuplot file : load "a_main.plt"
 set zeroaxis
 plot "data",\
 cos(x)
 reset

Résultat après le deuxième appel de G_plot():

 # Gnuplot file : load "a_main.plt"
 set zeroaxis
 plot "data",\
 sin(x)
 reset


Exemple numérique[modifier | modifier le wikicode]

Passer des pointeurs de fonctions à une fonction.


Les fonctions f‘ et f‘‘[modifier | modifier le wikicode]

  • Calculer la dérivée première et seconde d'une fonction.


/* ------------------------------ */
/* Save as c03.c                  */
/* ------------------------------ */
#include    <stdio.h>
#include     <math.h>

/* ------------------------------ */
double f(double x){return( pow(x,2.));}
char  feq[] = "x**2";

/* ------------------------------ */
double g(double x){return(
 pow(cos(x),2.)+sin(x)+x-3);}
char  geq[] = "cos(x)**2+sin(x)+x-3";

/* ------------------------------
 f'(a) = f(a+h) - f(a-h)
          -------------
              2h
   ------------------------------ */
double Dx_1(
double (*P_f)(double x),/* Declaration de pointeur de fonction */
double a,
double h
)
{
 return( ( ((*P_f)(a+h))-((*P_f)(a-h)) ) / (2.*h) );
}

/* -----------------------------
 f''(a) = f(a+h) - 2 f(a) + f(a-h)
           ----------------------
                     h**2
   ------------------------------- */
double Dx_2(
double (*P_f)(double x),/* Declaration de pointeur de fonction */
double a,
double h
)
{
 return( (((*P_f)(a+h))-2*((*P_f)(a))+((*P_f)(a-h))) / (h*h) );
}

/* ------------------------------ */
int main(void)
{
double x = 2.;
double h = 0.001;

printf("\n\n");

printf("  f(%.3f) = %.3f  \n",x,f(x)       );
printf(" f'(%.3f) = %.3f  \n",x,Dx_1(f,x,h));
printf("f''(%.3f) = %.3f  \n",x,Dx_2(f,x,h));

printf("\n\n");

printf("  g(%.3f) = %.3f \n",x,g(x)       );
printf(" g'(%.3f) = %.3f \n",x,Dx_1(g,x,h));
printf("g''(%.3f) = %.3f \n",x,Dx_2(g,x,h));

    printf("\n\n Press return to continue.");

 getchar();

 return 0;
}


Résultat :

  f(2.000) = 4.000
 f‘(2.000) = 4.000
f‘‘(2.000) = 2.000
.
  g(2.000) = 0.082
 g‘(2.000) = 1.341
g‘‘(2.000) = 0.398
.
Press return to continue.


La fonction FoG[modifier | modifier le wikicode]

  • Ici on passe les deux fonctions f et g à la fonction FoG().
  • La même fonction peut calculer gof, fog et fof...


/* ------------------------------ */
/* Save as c04.c                  */
/* ------------------------------ */
#include    <stdio.h>
#include     <math.h>

/* ------------------------------ */
double f(double x){return( pow(x,2.));}
char  feq[] = "x**2";

/* ------------------------------ */
double g(double x){return(2.0*x + 3.0);}
char  geq[] = "2.0*x + 3.0";

/* ------------------------------ */
double FoG(
double (*P_F)(double x),/* Pointeur pour la première fonction */
double (*P_G)(double x),/* Pointeur pour la deuxième fonction */
double a
)
{
 return((*P_F)( ((*P_G)(a))) );
}

/* ------------------------------ */
int main(void)
{
double a = 2.0;

 printf(" f : x-> %s\n", feq);
 printf(" g : x-> %s\n", geq);
 printf(" \n\n");

   printf(" f(g(%.0f)) = %6.1f\n", a, FoG(f,g,a));
   printf(" g(f(%.0f)) = %6.1f\n", a, FoG(g,f,a));
   printf(" f(f(%.0f)) = %6.1f\n", a, FoG(f,f,a));

 printf("\n\n Press return to continue.\n");
 getchar();

 return 0;
}

Résultat :

f : x-> x**2
g : x-> 2.0*x + 3.0
.
f(g(2)) = 49.0
g(f(2)) = 11.0
f(f(2)) = 16.0
.
Press return to continue.


Version main() avec sortie dans le fichier "list.txt"[modifier | modifier le wikicode]

  • Déclarer le pointeur de fichiers.
    • FILE *fp;
  • Ouvrir le fichier.
    • fp = fopen("list.txt","w");
  • Fermer le fichiers
    • fclose(fp);
  • Remplacer tous les printf( par fprintf(fp,
    • fprintf(fp,


/* ------------------------------ */
int main(void)
{
FILE   *fp; 

double a = 2.0;

 fp = fopen("list.txt","w"); 
 fprintf(fp," f : x-> %s\n", feq);
 fprintf(fp," g : x-> %s\n", geq);
 fprintf(fp," \n\n");

   fprintf(fp," f(g(%.0f)) = %6.1f\n", a, FoG(f,g,a));
   fprintf(fp," g(f(%.0f)) = %6.1f\n", a, FoG(g,f,a));
   fprintf(fp," f(f(%.0f)) = %6.1f\n", a, FoG(f,f,a));

 fclose(fp);

 printf("\n\n Press return to continue.\n");
 getchar();

 return 0;
}
/* ------------------------------ */