C pointeurs/Pointeurs de fonctions

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
  • 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

Dessiner deux fonctions successivement

modifier
  • 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

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

Passer des pointeurs de fonctions à une fonction.


Les fonctions f‘ et f‘‘

modifier
  • 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
  • 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
  • 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;
}
/* ------------------------------ */