Nous allons apprendre à organiser notre code en fonctions. Il s'agit en fait de découper nos programmes en petits morceaux. Chaque petit morceau sera ce qu'on appelle 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.
Créez une fonction
Voilà comment on représente une fonction, schématiquement (c'est un modèle à connaître !) :
type nomFonction(parametres)
{
// Insérez vos instructions ici
}
type
(correspond à la sortie) : c'est le type de la fonction.
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, elles seront alors de type void
("vide", en français).
nomFonction
: c'est le nom de votre fonction.
Vous pouvez appeler votre fonction comme vous voulez, du moment que vous respectez les mêmes règles que pour les variables (pas d'accents, pas d'espaces, etc.).
parametres
(correspond à l'entrée) : ce sont les paramètres de la fonction.
Ils sont entre parenthèses. Ce sont en fait des valeurs avec lesquelles la fonction va travailler.
Maintenant que vous savez ça, voyons un exemple pratique ! Disons que :
notre fonction
triple
reçoit un nombre entier de typeint
;et qu'elle renvoie un nombre entier également de type
int
.
Elle calcule le triple du nombre qu'on lui donne :
int triple(int nombre)
{
int resultat = 0;
resultat = 3 * nombre; // On multiplie le nombre fourni par 3
return resultat; // On retourne la variable resultat qui vaut le triple de nombre
}
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
.
Ce code signifie pour la fonction :
« Arrête-toi là et renvoie le nombre
resultat
».
Mais est-ce la façon la plus courte d'écrire notre fonction triple
?
Non, on peut faire tout cela en une ligne :
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.
Affectez (ou non) des paramètres à une fonction
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.
Affectez plusieurs paramètres à une fonction
Notre fonction triple
contient un paramètre, mais il est possible de créer des fonctions acceptant plusieurs paramètres, comme par exemple une fonction addition
qui additionne deux nombres a
et b
:
int addition(int a, int b)
{
return a + b;
}
N'affectez aucun paramètre à fonction
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 forcément toujours le même texte, puisque la fonction ne reçoit aucun paramètre susceptible de modifier son comportement !
Imaginons une fonction bonjour
qui affiche juste "Bonjour" à l'écran :
void bonjour()
{
printf("Bonjour");
}
Je n'ai rien mis entre parenthèses car la fonction ne prend aucun paramètre. De plus, j'ai utilisé le type void
dont je vous ai parlé plus haut.
En effet, ma fonction n'a pas non plus de return
: elle ne retourne rien.
Appelez une fonction
Nous allons reprendre notre fonction triple
(décidément, je l'aime bien) pour calculer le triple d'un nombre.
Pour le moment, écrivez la fonction triple
AVANT la fonction main
(si vous la placez après, ça ne marchera pas, je vous expliquerai pourquoi par la suite).
Testez donc ce code pour comprendre :
#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
:
On demande à l'utilisateur d'entrer un nombre.
On envoie ce nombre qu'il a entré à 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 :
nombreTriple = triple(nombreEntre);
Entre parenthèses, on envoie à la fonction triple
une variable en entrée (c'est le nombre sur lequel elle va travailler).
Cette fonction renvoie une valeur qu'on récupère dans la variable nombreTriple
.
Dans cette ligne de code, on ordonne donc à l'ordinateur :
« Demande à la fonction
triple
de me calculer le triple denombreEntre
,et stocke le résultat dans la variable
nombreTriple
».
Dans la vidéo suivante, nous allons reprendre le même exemple, et voir les différentes étapes pour créer la fonction triple
et l’appeler dans le main
:
Comprenez le sens de lecture d'une fonction
Le code ci-dessous est commenté de manière un peu particulière. C'est pour vous montrer dans quel ordre le code est "lu". Commencez donc par lire la ligne commentée 1, puis 2, puis 3 (vous avez compris 🤣) :
#include <stdio.h>
#include <stdlib.h>
int triple(int nombre) // 6
{
return 3 * nombre; // 7
}
int main(int argc, char *argv[]) // 1
{
int nombreEntre = 0, nombreTriple = 0; // 2
printf("Entrez un nombre... "); // 3
scanf("%d", &nombreEntre); // 4
nombreTriple = triple(nombreEntre); // 5
printf("Le triple de ce nombre est %d\n", nombreTriple); // 8
return 0; // 9
}
Voici ce qui se passe, ligne par ligne.
Le programme commence par la fonction
main
.Il lit les instructions dans la fonction, une par une, dans l'ordre.
Il lit l'instruction suivante et fait ce qui est demandé (
printf
).De même, il lit l'instruction et fait ce qui est demandé (
scanf
).Il lit l'instruction… Ah ! On appelle la fonction
triple
, on doit donc sauter à la ligne de la fonctiontriple
plus haut.On saute à la fonction
triple
et on récupère un paramètre (nombre
).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.On retourne dans
main
pour prendre l'instruction suivante.Un
return
: la fonctionmain
se termine, et donc le programme est terminé.
Si vous avez compris dans quel ordre l'ordinateur lit les instructions, vous avez déjà compris le principal.
Voici un exemple d'utilisation du programme :
Entrez un nombre... 10 Le triple de ce nombre est 30
Regardez bien ceci, c'est le même code mais il y a un changement au niveau du dernier printf
. De plus, on n'a pas déclaré de variable nombreTriple
car on ne s'en sert plus :
#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;
}
triple(nombreEntre)
est directement envoyé au printf
.
Que fait l'ordinateur quand il tombe sur cette ligne ?
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 qu'il doit d'abord appeler la fonction triple
pour envoyer ce nombre à la fonction printf
:
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. Et le plus fin dans tout ça, 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 LEGO.
Intégrez le principe en pratique avec ces exemples
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 rien de nouveau, mais ce 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.
Analysez une fonction qui prend 1 paramètre
Intéresserons-nous à une fonction qui ne renvoie rien (pas de sortie). Imaginons une fonction qui copie des lignes, comme les punitions que l'on avait lorsqu'on était petit :
void punition(int nombreDeLignes)
{
int i;
for (i = 0 ; i < nombreDeLignes ; i++)
{
printf("Je ne dois pas copier sur mon voisin\n");
}
}
int main(int argc, char *argv[])
{
punition(10);
return 0;
}
C'est une fonction qui affiche le même message à l'écran autant de fois qu'on lui demande. Elle prend un paramètre en entrée : le nombre de fois où il faut afficher la punition.
Résultat :
Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur mon voisin Je ne dois pas copier sur 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).
Il aurait été bien plus intéressant de créer une fonction punition
qui s'adapte à n'importe quelle sanction. On lui aurait envoyé deux paramètres : le texte à répéter, et le nombre de fois qu'il doit être répété.
Analysez une fonction qui prend 2 paramètres en entrée
Imaginons une fonction qui calcule l'aire d'un rectangle. L'aire d'un rectangle est facile à calculer :largeur * hauteur
.
Notre fonction nommée aireRectangle
va prendre deux paramètres : la largeur et la hauteur pour renvoyer l'aire :
double aireRectangle(double largeur, double hauteur)
{
return largeur * hauteur;
}
int main(int argc, char *argv[])
{
printf("Rectangle de largeur 5 et hauteur 10. Aire = %f\n", aireRectangle(5, 10));
printf("Rectangle de largeur 2.5 et hauteur 3.5. Aire = %f\n", aireRectangle(2.5, 3.5));
printf("Rectangle de largeur 4.2 et hauteur 9.7. Aire = %f\n", aireRectangle(4.2, 9.7));
return 0;
}
Rectangle de largeur 5 et hauteur 10. Aire = 50.000000 Rectangle de largeur 2.5 et hauteur 3.5. Aire = 8.750000 Rectangle de largeur 4.2 et hauteur 9.7. Aire = 40.740000
Pourrait-on afficher directement la largeur, la hauteur 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 :
void aireRectangle(double largeur, double hauteur)
{
double aire = 0;
aire = largeur * hauteur;
printf("Rectangle de largeur %f et hauteur %f. Aire = %f\n", largeur, hauteur, aire);
}
int main(int argc, char *argv[])
{
aireRectangle(5, 10);
aireRectangle(2.5, 3.5);
aireRectangle(4.2, 9.7);
return 0;
}
printf
est à l'intérieur de la fonction aireRectangle
et produit le même affichage que tout à l'heure. C'est juste une façon différente de procéder.
Analysez une fonction qui ne prend aucun paramètre en entrée
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.
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;
}
La fonction menu
affiche à nouveau le menu tant que l'utilisateur n'a pas entré 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 une méthode rapide et pratique.
En résumé
Les fonctions s'appellent entre elles. Ainsi, le
main
peut appeler des fonctions toutes prêtes telles queprintf
ouscanf
, mais aussi des fonctions que nous avons créées.Une fonction récupère en entrée des variables qu'on appelle les paramètres.
Elle effectue certaines opérations avec ces paramètres, puis retourne en général une valeur à l'aide de l'instruction
return
.
Dans le prochain chapitre, vous allez vous initiez à la programmation modulaire… J'espère que cela vous plaira ! Cela nous permettra de clôturer cette partie avant de nous attaquer à un gros morceau : les pointeurs.