Les fonctions

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Superman

V
Ancien staff
Dec 2, 2009
2,489
0
596
Créer et appeler une fonction

Nous avons vu dans les tous premiers chapitres qu'un programme en C commençait par une fonction appelée "main".
Je vous avais d'ailleurs même fait un schéma récapitulatif, pour vous rappeler quelques mots de vocabulaire. Attendez que je retrouve ce schéma
unsure.gif


* va fouiller dans les archives poussièreuses *

Ah je l'ai
heureux.png

Souvenirs souvenirs :

163840.png



C'était au tout début hein
clin.png

En haut, les directives de préprocesseur (un nom barbare sur lequel on reviendra d'ailleurs). Ces directives sont faciles à identifier : elles commencent par un # et sont généralement mises tout en haut des fichiers sources.

Puis en-dessous, il y avait ce que j'avais déjà appelé "une fonction". Ici, sur mon schéma, vous voyez une fonction "main" (pas trop remplie il faut le reconnaître
hihi.png
)
Je vous avais dit qu'un programme en langage C commençait par la fonction main. Que je vous rassure, c'est toujours vrai
heureux.png


Seulement, jusqu'ici nous sommes restés à l'intérieur de la fonction main. Nous n'en sommes jamais sortis. Revoyez vos codes sources et vous le verrez : nous sommes toujours restés à l'intérieur des accolades de la fonction main.

Eh bien, c'est mal d'avoir fait ça ?


Non ce n'est pas "mal", mais ce n'est pas ce que les programmeurs en C font dans la réalité.
Quasiment aucun programme n'est écrit uniquement à l'intérieur des accolades de la fonction "main". Jusqu'ici nos programmes étaient courts, donc ça ne posait pas de gros problèmes, mais imaginez des plus gros programmes qui font des milliers de lignes de code ! Si tout était concentré dans la fonction main, bonjour le bordel
rire.gif


Nous allons donc maintenant apprendre à nous organiser. Nous allons en fait découper nos programmes en petits bouts (souvenez-vous de l'image des legos que je vous ai donnée tout à l'heure).
Chaque "petit bout de programme" sera ce qu'on appelle une fonction.

Quel est le but d'une fonction ?


Une fonction exécute des actions et renvoie un résultat. C'est un morceau de code qui sert à faire quelque chose de précis.
On dit qu'une fonction possède une entrée et une sortie. Schématiquement, ça donne quelque chose comme ça :

8001.png



Lorsqu'on appelle une fonction, il y a 3 étapes :


  1. L'entrée: on fait "rentrer" des informations dans la fonction (en lui donnant des informations avec lesquelles travailler)
  2. Les calculs : grâce aux informations qu'elle a reçues en entrée, la fonction travaille.
  3. La sortie : une fois qu'elle a fini ses calculs, la fonction renvoie un résultat. C'est ce qu'on appelle la sortie, ou encore le retour.


Concrètement, on peut imaginer par exemple une fonction appelée "triple" qui calcule le triple du nombre qu'on lui donne (en le multipliant par 3) :

8002.png



Bien entendu, les fonctions seront en général plus compliquées
clin.png

Le but des fonctions est donc de simplifier le code source, pour ne pas avoir à retaper le même code plusieurs fois d'affilée.

Rêvez un peu : plus tard, nous créerons par exemple une fonction "afficherFenetre" qui ouvrira une fenêtre à l'écran. Une fois la fonction écrite (c'est l'étape la plus difficile), on n'aura plus qu'à dire "Hep toi la fonction afficherFenetre, ouvre-moi une fenêtre !"
clin.png

On pourra aussi écrire une fonction "deplacerPersonnage" dont le but sera de déplacer le personnage d'un jeu à l'écran etc etc
heureux.png



Schéma d'une fonction



Vous avez déjà eu un aperçu de comment est faite une fonction avec la fonction main.
Cependant pour bien que vous compreniez il va falloir que je vous montre quand même comment on construit une fonction.

Voici le schéma d'une fonction, à retenir par coeur :

Code : C1
2
3
4
type nomFonction(parametres)
{
// Insérez vos instructions ici
}




Vous reconnaissez là un peu la forme de la fonction main.
Voici ce qu'il faut savoir sur ce schéma :


  • type (correspond à la sortie) : c'est le type de la fonction. Comme les variables, les fonctions ont un type. Ce type dépend du résultat que la fonction renvoie : si la fonction renvoie un nombre décimal, vous mettrez sûrement double, si elle renvoie un entier vous mettrez int ou long par exemple. Mais il est aussi possible de créer des fonctions qui ne renvoient rien !
    Il y a donc 2 sortes de fonctions :
    • Les fonctions qui renvoient une valeur : on leur met un des types que l'on connaît (char, int, double...)
    • Les fonctions qui ne renvoient pas de valeur : on leur met un type spécial "void" (qui signifie "vide").
  • nomFonction : c'est le nom de votre fonction. Vous pouvez appeler votre fonction comme vous voulez, du temps que vous respectez les mêmes règles que pour les variables (pas d'accents, pas d'espaces etc).
  • parametres (correspond à l'entrée) : entre parenthèses, vous pouvez envoyer des paramètres à la fonction. Ce sont des valeurs avec lesquelles la fonction va travailler.
    Par exemple, pour une fonction "triple", vous envoyez un nombre en paramètre. La fonction "récupère" ce nombre et en calcule le triple, en le multipliant par 3. Elle renvoie ensuite le résultat de ses calculs.
    Vous pouvez envoyer autant de paramètres que vous le voulez.
    Vous pouvez aussi n'envoyer aucun paramètre à la fonction, mais ça se fait plus rarement.
  • Ensuite vous avez les accolades qui indiquent le début et la fin de la fonction. A l'intérieur de ces accolades vous mettrez les instructions que vous voulez. Pour la fonction triple, il faudra taper des instructions qui multiplient par 3 le nombre reçu en entrée.


Une fonction, c'est donc un mécanisme qui reçoit des valeurs en entrée (les paramètres) et qui renvoie un résultat en sortie.


Créer une fonction



Voyons voir un exemple pratique sans plus tarder : la fameuse fonction "triple" dont je vous parle depuis tout à l'heure. On va dire que cette fonction reçoit un nombre entier de type int et qu'elle renvoie un nombre entier aussi de type int. Cette fonction calcule le triple du nombre qu'on lui donne :

Code : C1
2
3
4
5
6
7
int triple(int nombre)
{
int resultat = 0;

resultat = 3 * nombre; // On multiplie le nombre qu'on nous a transmis par 3
return resultat; // On retourne la variable resultat qui vaut le triple de nombre
}




Voilà notre première fonction
heureux.png

Une première chose importante : comme vous le voyez, la fonction est de type int. Elle doit donc renvoyer une valeur de type int.

Entre les parenthèses, vous avez les variables que la fonction reçoit. Ici, notre fonction triple reçoit une variable de type int appelée "nombre".

La ligne qui indique de "renvoyer une valeur" est celle qui contient le "return". Cette ligne se trouve généralement à la fin de la fonction, après les calculs.
return resultat; dit à la fonction : arrête-toi là et renvoie le nombre "resultat". Cette variable "resultat" DOIT être de type int, car la fonction renvoie un int comme on l'a dit plus haut
clin.png


La variable resultat est déclarée (= créée) dans la fonction "triple". Cela signifie qu'elle n'est utilisable que dans cette fonction, et pas dans une autre comme la fonction "main" par exemple. C'est donc une variable propre à la fonction "triple".


Mais est-ce la façon la plus courte de faire notre fonction triple ?
Non, on peut faire ça en une ligne en fait
clin.png


Code : C1
2
3
4
int triple(int nombre)
{
return 3 * nombre;
}




Cette fonction fait exactement la même chose que la fonction de tout à l'heure, elle est juste plus rapide à écrire
smile.png

Généralement, vos fonctions contiendront plusieurs variables pour effectuer leurs calculs et leurs opérations, rares seront les fonctions aussi courtes que "triple"
clin.png



Plusieurs paramètres, aucun paramètre



Plusieurs paramètres



Notre fonction "triple" contient un paramètre, mais il est possible de créer des fonctions prenant plusieurs paramètres.
Par exemple, une fonction addition qui additionne deux nombres a et b :

Code : C1
2
3
4
int addition(int a, int b)
{
return a + b;
}




Il suffit de séparer les différents paramètres par une virgule comme vous le voyez
clin.png


Aucun paramètre



Certaines fonctions, plus rares, ne prennent aucun paramètre en entrée. Ces fonctions feront généralement toujours la même chose. En effet, si elles n'ont pas de nombres sur lesquels travailler, vos fonctions serviront juste à effectuer certaines actions, comme afficher du texte à l'écran (et encore, ce sera toujours le même texte !)

Imaginons une fonction "bonjour" qui affiche juste bonjour à l'écran :

Code : C1
2
3
4
void bonjour()
{
printf("Bonjour");
}




Je n'ai rien mis entre parenthèses car la fonction ne prend aucun paramètre.
De plus, j'ai mis le type "void" dont je vous ai parlé plus haut.

En effet, comme vous le voyez ma fonction n'a pas non plus de "return". Elle ne retourne rien. Une fonction qui ne retourne rien est de type void.


Appeler une fonction



On va maintenant tester un code source pour pratiquer un peu avec ce qu'on vient d'apprendre.
Nous allons utiliser notre fonction "triple" (décidemment je l'aime bien) pour calculer le triple d'un nombre.

Pour le moment, je vous demande d'écrire la fonction "triple" AVANT la fonction main. Si vous la mettez après, ça ne marchera pas. Je vous expliquerai pourquoi par la suite
clin.png


Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>

int triple(int nombre)
{
return 3 * nombre;
}

int main(int argc, char *argv[])
{
int nombreEntre = 0, nombreTriple = 0;

printf("Entrez un nombre... ");
scanf("%d", &nombreEntre);

nombreTriple = triple(nombreEntre);
printf("Le triple de ce nombre est %d\n", nombreTriple);

return 0;
}




Notre programme commence par la fonction main comme vous le savez.
On demande à l'utilisateur de rentrer un nombre. On envoie ce nombre qu'il a rentré à la fonction triple, et on récupère le résultat dans la variable nombreTriple. Regardez en particulier cette ligne, c'est la plus intéressante car c'est l'appel de la fonction :

Code : C1
nombreTriple = triple(nombreEntre);




Entre parenthèses, on envoie une variable en entrée à la fonction triple, c'est le nombre sur lequel elle va travailler.
Cette fonction renvoie une valeur, valeur qu'on récupère dans la variable nombreTriple. On demande donc à l'ordinateur dans cette ligne : "Demande à la fonction triple de me calculer le triple de nombreEntre, et stocke le résultat dans la variable nombreTriple".


Les mêmes explications sous forme de schéma



Vous avez encore du mal à comprendre comment ça fonctionne concrètement ?
Pas de panique ! Je suis sûr que vous allez comprendre avec mes schémas
smile.png


Ce code particulièrement commenté vous indique dans quel ordre le code est lu. Commencez donc par lire la ligne numérotée "1", puis "2", puis "3" (bon vous avez compris je crois
heureux.png
)

Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>

int triple(int nombre) // 6) On saute à la fonction triple et on récupère un paramètre (nombre)
{
return 3 * nombre; // 7) On fait des calculs sur le nombre et on termine la fonction. Return signifie la fin de la fonction et permet d'indiquer le résultat à renvoyer
}

int main(int argc, char *argv[]) // 1) Le programme commence par la fonction main (cette ligne)
{
int nombreEntre = 0, nombreTriple = 0; // 2) Il lit les instructions dans la fonction une par une dans l'ordre

printf("Entrez un nombre... "); // 3) Il lit l'instruction suivante et fait ce qui est demandé (printf)
scanf("%d", &nombreEntre); // 4) Pareil, il lit l'instruction et fait ce qui est demandé (scanf)

nombreTriple = triple(nombreEntre); // 5) Il lit l'instruction... Ah ! On appelle la fonction triple, on doit donc sauter à la ligne de la fonction triple plus haut
printf("Le triple de ce nombre est %d\n", nombreTriple); // 8) On retourne dans le main à l'instruction suivante

return 0; // 9) Un return ! La fonction main se termine et donc le programme est terminé.
}




Si vous avez compris dans quel ordre l'ordinateur lisait les instructions, vous avez déjà compris le principal
smile.png



Maintenant, il faut bien comprendre qu'une fonction reçoit des paramètres en entrée et renvoie une valeur en sortie.

164003.png



Note : ce n'est pas tout le temps le cas comme ça pour toutes les fonctions. Parfois, une fonction ne prend aucun paramètre en entrée, ou au contraire elle en prend plusieurs (je vous ai expliqué ça un peu plus haut).
De même, parfois une fonction renvoie une valeur, parfois elle ne renvoie rien (dans ce cas il n'y a pas de return).


Testons ce programme



Voici un exemple d'utilisation du programme (y'a rien de bien extraordinaire car c'est une fonction toute bête hein
clin.png
) :

Code : Console
Entrez un nombre... 10

Le triple de ce nombre est 30



Vous n'êtes pas obligés de stocker le résultat d'une fonction dans une variable ! Vous pouvez directement envoyer le résultat de la fonction triple à une autre fonction, comme si triple(nombreEntre) était une variable.


Regardez bien ceci, c'est le même code mais y'a un changement au niveau du dernier printf, et on n'a pas déclaré de variable nombreTriple car on ne s'en sert plus :

Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>

int triple(int nombre)
{
return 3 * nombre;
}

int main(int argc, char *argv[])
{
int nombreEntre = 0;

printf("Entrez un nombre... ");
scanf("%d", &nombreEntre);

// Le résultat de la fonction est directement envoyé au printf et n'est pas stocké dans une variable
printf("Le triple de ce nombre est %d\n", triple(nombreEntre));

return 0;
}




Comme vous le voyez, triple(nombreEntre) est directement envoyé au printf.
Que fait l'ordinateur quand il tombe sur cette ligne ?

C'est très simple. Il voit que la ligne commence par printf, il va donc appeler la fonction printf.
Il envoie à la fonction printf tous les paramètres qu'on lui donne. Le premier paramètre est le texte à afficher, et le second est un nombre.
Votre ordinateur voit que pour envoyer ce nombre à la fonction printf il doit d'abord appeler la fonction triple. C'est ce qu'il fait : il appelle triple, il effectue les calculs de triple, et une fois qu'il a le résultat il l'envoie directement dans la fonction printf !

C'est un peu une imbrication de fonctions
clin.png


Et le top, c'est qu'une fonction peut en appeler une autre à son tour !
Notre fonction triple pourrait appeler une autre fonction, qui elle-même appellerait une autre fonction etc... C'est ça le principe de la programmation en C ! Tout est combiné, comme dans un jeu de Legos
clin.png


Au final, le plus dur sera d'écrire vos fonctions. Une fois que vous les aurez écrites, vous n'aurez plus qu'à appeler les fonctions sans vous soucier des calculs qu'elles peuvent bien faire à l'intérieur. Ca va permettre de simplifier considérablement l'écriture de nos programmes, et ça croyez-moi on en aura bien besoin !
smile.png

Plein d'exemples pour bien comprendre

Vous avez dû vous en rendre compte : je suis un maniaque des exemples.
La théorie c'est bien, mais si on ne fait que ça on risque de ne pas retenir grand chose, et surtout ne pas comprendre comment s'en servir, ce qui serait un peu dommage
langue.png


Je vais donc maintenant vous montrer plusieurs exemples d'utilisation de fonctions, pour que vous ayez une idée de leur intérêt. Je vais m'efforcer de faire des cas différents à chaque fois, pour que vous puissiez avoir des exemples de tous les types de fonctions qui peuvent exister.

Je ne vous apprendrai pas grand chose de nouveau, mais ça sera l'occasion de voir des exemples pratiques. Si vous avez déjà compris tout ce que j'ai expliqué avant, c'est très bien et normalement aucun des exemples qui vont suivre ne devrait vous surprendre
clin.png



Conversion euros / francs



On commence par une fonction très similaire à "triple", qui a quand même un minimum d'intérêt cette fois : une fonction qui convertit les euros en francs.
Pour ceux d'entre vous qui ne connaîtraient pas ces monnaies (il n'y a pas que des français sur le Site du Zér0 hein
clin.png
) sachez que :

1 euro = 6.55957 francs

On va créer une fonction appelée conversion.
Cette fonction prend une variable en entrée de type double et retourne une sortie de type double (on va forcément manipuler des chiffres décimaux !).

Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
double conversion(double euros)
{
double francs = 0;

francs = 6.55957 * euros;
return francs;
}

int main(int argc, char *argv[])
{
printf("10 euros = %fF\n", conversion(10));
printf("50 euros = %fF\n", conversion(50));
printf("100 euros = %fF\n", conversion(100));
printf("200 euros = %fF\n", conversion(200));

return 0;
}




Code : Console
10 euros = 65.595700F

50 euros = 327.978500F

100 euros = 655.957000F

200 euros = 1311.914000F



Il n'y a pas grand chose de différent par rapport à la fonction triple je vous avais prévenu
langue.png

D'ailleurs, ma fonction conversion est un peu longue et pourrait être raccourcie en une ligne, je vous laisse le faire je vous ai déjà expliqué comment faire plus haut.

Dans la fonction main, j'ai fait exprès de faire plusieurs printf pour vous montrer l'intérêt d'avoir une fonction. Pour obtenir la valeur de 50 euros, je n'ai qu'à écrire conversion(50). Et si je veux avoir la conversion en francs de 100 euros, j'ai juste besoin de changer le paramètre que j'envoie à la fonction (100 au lieu de 50).


A vous de jouer ! Ecrivez une seconde fonction (toujours avant la fonction main) qui fera elle la conversion inverse : Francs => Euros. Pas bien difficile hein, y'a juste un signe d'opération à changer
clin.png



La punition



On va maintenant s'intéresser à une fonction qui ne renvoie rien (pas de sortie).
C'est une fonction qui affiche le même message à l'écran autant de fois qu'on lui demande. Cette fonction prend un paramètre en entrée : le nombre de fois où il faut afficher la punition.


Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void punition(int nombreDeLignes)
{
int i;

for (i = 0 ; i < nombreDeLignes ; i++)
{
printf("Je ne dois pas recopier mon voisin\n");
}
}

int main(int argc, char *argv[])
{
punition(10);

return 0;
}




Code : Console
Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin

Je ne dois pas recopier mon voisin



On a ici affaire à une fonction qui ne renvoie aucune valeur. Cette fonction se contente juste d'effectuer des actions (ici, elle affiche des messages à l'écran).
Une fonction qui ne renvoie aucune valeur est de type "void", c'est pour cela qu'on a écrit void.

A part ça, rien de bien différent
clin.png


Il aurait été bien plus intéressant de créer une fonction "punition" qui s'adapte à n'importe quelle punition. On lui aurait envoyé 2 paramètres : le texte à répéter, et le nombre de fois qu'il doit être répété. Le problème, c'est qu'on ne sait pas encore gérer le texte en C (au cas où vous auriez pas les yeux très ouverts, je vous rappelle qu'on fait que manipuler des variables contenant des nombres depuis le début
langue.png
)
D'ailleurs à ce sujet, je vous annonce que nous ne tarderons pas à apprendre à utiliser des variables qui retiennent du texte. C'est que c'est plus compliqué qu'il n'y paraît, et on ne pouvait pas l'apprendre dès le début du cours
clin.png



Aire d'un rectangle



L'aire d'un rectangle est facile à calculer : largeur * longueur.
Notre fonction aireRectangle va prendre 2 paramètres, la largeur et la longueur. Elle renverra l'aire :

Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
double aireRectangle(double largeur, double longueur)
{
return largeur * longueur;
}

int main(int argc, char *argv[])
{
printf("Rectangle de largeur 5 et longueur 10. Aire = %f\n", aireRectangle(5, 10));
printf("Rectangle de largeur 2.5 et longueur 3.5. Aire = %f\n", aireRectangle(2.5, 3.5));
printf("Rectangle de largeur 4.2 et longueur 9.7. Aire = %f\n", aireRectangle(4.2, 9.7));

return 0;
}




Code : Console
Rectangle de largeur 5 et longueur 10. Aire = 50.000000

Rectangle de largeur 2.5 et longueur 3.5. Aire = 8.750000

Rectangle de largeur 4.2 et longueur 9.7. Aire = 40.740000




Pourrait-on afficher directement la largeur, la longueur et l'aire dans la fonction ?


Bien sûr !
Dans ce cas, la fonction ne renverrait plus rien, elle se contenterait de calculer l'aire et de l'afficher immédiatement.

Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void aireRectangle(double largeur, double longueur)
{
double aire = 0;

aire = largeur * longueur;
printf("Rectangle de largeur %f et longueur %f. Aire = %f\n", largeur, longueur, aire);
}

int main(int argc, char *argv[])
{
aireRectangle(5, 10);
aireRectangle(2.5, 3.5);
aireRectangle(4.2, 9.7);

return 0;
}




Comme vous le voyez, le printf est à l'intérieur de la fonction aireRectangle et fait le même affichage que tout à l'heure. C'est juste une façon différente de procéder
clin.png



Un menu



Ce code est plus intéressant et concret. On crée une fonction menu() qui ne prend aucun paramètre en entrée. Cette fonction se contente d'afficher le menu, et demande à l'utilisateur de faire un choix.
La fonction renvoie le choix de l'utilisateur.

Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
int menu()
{
int choix = 0;

while (choix < 1 || choix > 4)
{
printf("Menu :\n");
printf("1 : Poulet de dinde aux escargots rotis a la sauce bearnaise\n");
printf("2 : Concombres sucres a la sauce de myrtilles enrobee de chocolat\n");
printf("3 : Escalope de kangourou saignante et sa gelee aux fraises poivree\n");
printf("4 : La surprise du Chef (j'en salive d'avance...)\n");
printf("Votre choix ? ");
scanf("%d", &choix);
}

return choix;
}

int main(int argc, char *argv[])
{
switch (menu())
{
case 1:
printf("Vous avez pris le poulet\n");
break;
case 2:
printf("Vous avez pris les concombres\n");
break;
case 3:
printf("Vous avez pris l'escalope\n");
break;
case 4:
printf("Vous avez pris la surprise du Chef. Vous etes un sacre aventurier dites donc !\n");
break;
}

return 0;
}




J'en ai profité pour améliorer le menu (par rapport à ce qu'on faisait habituellement) : la fonction menu réaffiche le menu tant que l'utilisateur n'a pas rentré un nombre compris entre 1 et 4. Comme ça, aucun risque que la fonction renvoie un nombre qui ne figure pas au menu !

Dans le main, vous avez vu qu'on fait un switch(menu()). Une fois que la fonction menu() est terminée, elle renvoie le choix de l'utilisateur directement dans le switch. C'est pratique et rapide comme méthode
smile.png


A vous de jouer ! Le code est encore améliorable : on pourrait afficher un message d'erreur si l'utilisateur rentre un mauvais nombre plutôt que de bêtement réafficher le menu
clin.png



SOURCE : Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!