Previous Next Up Index Contents

10.7. Discussion de deux problèmes

"fonction" ou "procédure" ?

Problème 1: Ecrire une fonction qui lit un nombre entier au clavier en affichant un petit texte d'invite.

Réflexion: Avant d'attaquer le problème, nous devons nous poser la question, de quelle façon nous allons transférer la valeur lue dans la variable de la fonction appelante. Il se présente alors deux possibilités:

a) Nous pouvons fournir la valeur comme résultat de la fonction.

b) Nous pouvons affecter la valeur à une adresse que nous obtenons comme paramètre. Dans ce cas, le résultat de la fonction est void. Cette fonction est en fait une "procédure" au sens du langage Pascal et du langage algorithmique.

Résultat int ==> "fonction"

Reprenons d'abord la fonction ENTREE que nous avons définie au chapitre 10.3.:

int ENTREE(void)
{
 int NOMBRE;
 printf("Entrez un nombre entier : ");
 scanf("%d", &NOMBRE);
 return NOMBRE;
}
La fonction ENTREE fournit un résultat du type int qui est typiquement affecté à une variable,
int A;
A = ENTREE();
ou intégré dans un calcul:
   long SOMME;
   int I;
   for (I=0; I<10; I++)
      SOMME += ENTREE();
Résultat void ==> "procédure"

Nous pouvons obtenir le même effet que ENTREE en définissant une fonction ENTRER du type void, qui affecte la valeur lue au clavier immédiatement à une adresse fournie comme paramètre. Pour accepter cette adresse, le paramètre de la fonction doit être déclaré comme pointeur:

void ENTRER(int *NOMBRE)
{
 printf("Entrez un nombre entier : ");
 scanf("%d", NOMBRE);
}

Remarquez: Comme le paramètre NOMBRE est un pointeur, il n'a pas besoin d'être précédé du symbole & dans l'instruction scanf.

Lors de l'appel, nous devons transférer l'adresse de la variable cible comme paramètre:

int A;
ENTRER(&A);

Jusqu'ici, la définition et l'emploi de la fonction ENTRER peuvent sembler plus simples que ceux de la fonction ENTREE. Si nous essayons d'intégrer les valeurs lues par ENTRER dans un calcul, nous allons quand même constater que ce n'est pas toujours le cas:

   long SOMME;
   int I;
   int A;
   for (I=0; I<10; I++)
      {
       ENTRER(&A);
       SOMME += A;
      } 

Conclusions

Dans la plupart des cas, nous pouvons remplacer une fonction qui fournit un résultat par une fonction du type void qui modifie le contenu d'une variable de la fonction appelante. Dans le langage Pascal, nous dirions que nous pouvons remplacer une fonction par une procédure. En général, la préférence pour l'une ou l'autre variante dépend le l'utilisation de la fonction:

Conseil

Si le résultat de la fonction est typiquement intégré dans un calcul ou une expression, alors nous employons une fonction qui fournit un résultat. En fait, personne ne remplacerait une fonction comme

         double sin(double X)

par une fonction

         void sin(double *Y, double X)

* Si la charge principale d'une fonction est de modifier des données ou l'état de l'environnement, sans que l'on ait besoin d'un résultat, alors il vaut mieux utiliser une fonction du type void.

* Si une fonction doit fournir plusieurs valeurs comme résultat, il s'impose d'utiliser une procédure du type void. Ce ne serait pas une bonne solution de fournir une valeur comme résultat et de transmettre les autres valeurs comme paramètres.

Exemple

La fonction MAXMIN fournit le maximum et le minimum des valeurs d'un tableau T de N d'entiers. Comme nous ne pouvons pas fournir les deux valeurs comme résultat, il vaut mieux utiliser deux paramètres pointeurs MAX et MIN qui obtiendront les adresses cibles pour les deux valeurs. Ainsi la fonction MAXMIN est définie avec quatre paramètres:

void MAXMIN(int N, int *T, int *MAX, int *MIN);
{
 int I;
 *MAX=*T;
 *MIN=*T;
 for (I=1; I<N; I++)
     {
      if (*(T+I)>*MAX) *MAX = *(T+I);
      if (*(T+I)<*MIN) *MIN = *(T+I);
     }
}

Lors d'un appel de MAXMIN, il ne faut pas oublier d'envoyer les adresses des paramètres pour MAX et MIN.

int TAB[8] = {2,5,-1,0,6,9,-4,6};
int N = 8;
int MAXVAL, MINVAL;
MAXMIN(N, TAB, &MAXVAL, &MINVAL);

Pointeur ou indice numérique ?

Problème 2: Ecrire une fonction qui fournit la position du prochain signe d'espacement dans une chaîne de caractères ou la position de la fin de la chaîne si elle ne contient pas de signe d'espacement. Utiliser la fonction isspace de la bibliothèque <ctype> pour la recherche.

Réflexion: Il y a plusieurs possibilités de résoudre ce problème: Une "indication" d'une position dans une chaîne de caractères peut être fournie par un pointeur ou par un indice numérique. Dans la suite, nous allons développer les deux variations.

Dans les deux cas, nous avons besoin de l'adresse du tableau qui est passée comme paramètre char *CH à la fonction.

Résultat int

La fonction CHERCHE1 fournit l'indice de l'élément recherché comme résultat du type int.

int CHERCHE1(char *CH)
{
 int INDEX=0;
 while (*CH && !isspace(*CH))
   {
    CH++;
    INDEX++;
   }
 return INDEX;
}

Cette information peut être affectée à une variable:

   int I;
   char TXT[40];
   ...
   I = CHERCHE1(TXT);

ou être intégrée dans une expression en profitant même de l'arithmétique des pointeurs:

main()
{
 /* Prototype de la fonction appelée */
 int CHERCHE1(char *CH);
 char TXT[40];
 printf("Entrer une phrase : ");
 gets(TXT);
 /* Affichage de la phrase sans le premier mot */
 puts(TXT + CHERCHE1(TXT));
 return 0;
}

Résultat char*

La fonction CHERCHE2 fournit un pointeur sur l'élément recherché. Remarquez la déclaration du résutat de la fonction CHERCHE2 comme pointeur sur char:

char *CHERCHE2(char *CH)
{
 while (*CH && !isspace(*CH))
       CH++;
 return CH;
}   

Il se montre à nouveau que l'utilisation de pointeurs permet une solution très compacte et élégante. Dans cette version, nous n'avons plus besoin de variables d'aide et nous pouvons renvoyer la valeur modifiée du paramètre local CH comme résultat. L'utilisation de la fonction peut se présenter de façon aussi élégante:

main()
{
 /* Prototype de la fonction appelée */
 char *CHERCHE2(char *CH);
 char TXT[40];
 printf("Entrer une phrase : ");
 gets(TXT);
 /* Affichage de la phrase sans le premier mot */
 puts(CHERCHE2(TXT));
 return 0;
}

Conclusion

Lors du travail avec des tableaux et surtout avec des chaînes de caractères, il est toujours avantageux d'utiliser des pointeurs et de profiter de l'arithmétique des pointeurs. Les fonctions employant des pointeurs lors du traitement de tableaux permettent souvent des solutions très naturelles, d'autant plus qu'elles disposent des adresses des tableaux dans des paramètres locaux.


Previous Next Up Index Contents

Feedback - Copyright © 1993,1996,1997 F.Faber