====== Fiche savoirs sur les fonctions ======
**Définition :**
* Une fonction est un bloc de code isolé, qui peut être appelé et donc réutilisé plusieurs fois dans le code de son programme.
* l'utilisation des fonctions permet d'avoir un code organisé en modules.
===== Utiliser une fonctionpour éviter les répétitions de code =====
Voici l’exemple du programme **NombreCache** avec des contrôles de la saisie de l'essai (try catch) qui sont utilisés à plusieurs endroits dans le code de l'application et qui se ressemblent :
* le contrôle de la saisie avant la boucle (la première saisie)
* et le contrôle de la saisie dans la boucle:
static void Main(string[] args) {
// déclaration
int valeur = 0, essai = 0, nbre = 1;
bool correct = false;
// saisie du nombre à chercher
while (!correct) {
try {
Console.Write("Entrez le nombre à chercher = ");
valeur = int.Parse(Console.ReadLine());
correct = true;
}
catch {
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
Console.Clear();
// saisie du premier essai
correct = false;
while (!correct) {
try {
Console.Write("Entrez un essai = ");
essai = int.Parse(Console.ReadLine());
correct = true;
}
catch {
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
// boucle sur les essais
while (essai != valeur) {
// test de l’essai par rapport à la valeur à chercher
if (essai > valeur) {
Console.WriteLine(" --> trop grand !");
}
else {
Console.WriteLine(" --> trop petit !");
}
// saisie d’un nouvel essai
correct = false;
while (!correct) {
try {
Console.Write("Entrez un essai = ");
essai = int.Parse(Console.ReadLine());
correct = true;
}
catch {
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
// compteur d’essais
nbre++;
}
// valeur trouvée
Console.WriteLine("Vous avez trouvé en "+nbre+" fois !");
Console.ReadLine();
}
Le premier objectif est d’éviter la répétition à l'identique de plusieurs lignes de code en créant une **fonction appelée saisie()** en dehors du **Main()**, juste au-dessus, pour isoler le bloc de code identique :
static void saisie()
{
correct = false;
while (!correct)
{
try
{
Console.Write("Entrez un essai = ");
essai = int.Parse(Console.ReadLine());
correct = true;
}
catch
{
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
}
Problème :
* les variables **correct** et **essai** ne sont pas déclarées dans la fonction **saisie()**.
* il faut rajouter leur déclaration
La variable **correct** n'est utilisée que dans la fonction **saisie()** : on peut la déclarer directement dans la fonction **saisie()** :
static void saisie()
{
bool correct = false;
while (!correct)
{
try
{
Console.Write("Entrez un essai = ");
essai = int.Parse(Console.ReadLine());
correct = true;
}
catch
{
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
}
Par contre la variable **essai** doit pouvoir être réutilisée dans le **Main()**. Il est nécessaire que **essai** soit déclarée pour être visible et utilisable à la fois dans le **Main()** et dans la fonction **saisie()**. Il est préférable que **essai** soit déclarée comme une **variable globale** à l'ensemble du programme.
==== Déclaration de la variable globale essai : ====
class Program
{
static int essai;
...
==== Essai n'est plus déclarée dans le Main() : ====
// déclaration
int valeur = 0, nbre = 1;
essai = 0;
==== Programme du nombre caché avec la procédure saisie ====
static int essai;
static void Main(string[] args) {
// déclaration
int valeur = 0, nbre = 1;
bool correct = false;
// saisie du nombre à chercher
while (!correct) {
try {
Console.Write("Entrez le nombre à chercher = ");
valeur = int.Parse(Console.ReadLine());
correct = true;
}
catch {
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
Console.Clear();
// saisie du premier essai
saisie();
// boucle sur les essais
while (essai != valeur) {
// test de l’essai par rapport à la valeur à chercher
if (essai > valeur) {
Console.WriteLine(" --> trop grand !");
}
else {
Console.WriteLine(" --> trop petit !");
}
// saisie d’un nouvel essai
saisie();
// compteur d’essais
nbre++;
}
// valeur trouvée
Console.WriteLine("Vous avez trouvé en "+nbre+" fois !");
Console.ReadLine();
}
**Exercice 1 :**
* Créez un nouveau projet à partir de ce dépôt Git : https://github.com/ctecher/ModuleExercice_1.git
* Modifiez Le programme doit permettre de saisir plusieurs prix et au final d’afficher le total des prix.
* Avant chaque saisie, il faut poser la question "Avez-vous un prix à saisir ? (O/N) " et saisir la réponse de préférence d’un seul caractère sans valider, en contrôlant que l’utilisateur a bien saisi O ou N et pas autre chose (sinon la question est reposée).
* Si l’utilisateur répond N, le total des prix est affiché et le programme s’arrête.
* Sachant qu’une saisie doit être prévue avant la boucle générale, et une à la fin de la boucle, le but est d’isoler ce bloc de code dans une fonction.
{{ :bloc1:fonction_01.png?400 |}}
{{ :bloc1:fonction_02.png?400 |}}
===== Utiliser une fonction qui renvoie un résultat (une valeur)=====
Il est possible de ne pas utiliser la variable globale en transformant la fonction pour qu’elle **renvoie** (**retourne**) au programme appelant, la valeur saisie.
Il faut supprimer la déclaration de la variable globale **essai** et remettre sa déclaration dans le **Main()**, comme c’était avant :
//static int essai; à supprimer
...
static void Main(string[] args)
{
// déclaration
int valeur = 0, essai = 0, nbre = 1;
Il est nécessaire de déclarer la variable **essai** dans la fonction **saisie()**.
Cette déclaration va se faire :
* en changeant le nom de la variable pour l'appeler **nombre** et en l'initialisant en début de fonction ;
* en modifiant la déclaration de la fonction : **void** est devenu **int** car la fonction va **retourner** une information de type **int** ;
* en rajoutant à la fin de la fonction la ligne **return nombre;** qui permet de **retourner** le contenu de la variable **nombre** :
static int saisie()
{
int nombre = 0;
bool correct = false;
while (!correct)
{
try
{
Console.Write("Entrez un essai = ");
nombre = int.Parse(Console.ReadLine());
correct = true;
}
catch
{
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
return nombre;
}
Pour récupérer le retour de la fonction **saisie()** dan* le **Main()** il suffit d’affecter l’appel de la fonction, dans une variable.
Dans le **Main()**, l’appel de la fonction **saisie()** doit donc être affecté à la variable **essai** pour récupérer dans **essai** l’information saisie. Voici au final le **Main()** :
static void Main(string[] args) {
// déclaration
int valeur = 0, essai = 0, nbre = 1;
bool correct = false;
// saisie du nombre à chercher
while (!correct) {
try {
Console.Write("Entrez le nombre à chercher = ");
valeur = int.Parse(Console.ReadLine());
correct = true;
}
catch {
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
Console.Clear();
// saisie du premier essai
essai = saisie();
// boucle sur les essais
while (essai != valeur) {
// test de l’essai par rapport à la valeur à chercher
if (essai > valeur) {
Console.WriteLine(" --> trop grand !");
}
else {
Console.WriteLine(" --> trop petit !");
}
// saisie d’un nouvel essai
essai = saisie();
// compteur d’essais
nbre++;
}
// valeur trouvée
Console.WriteLine("Vous avez trouvé en "+nbre+" fois !");
Console.ReadLine();
}
**Exercice 2 :**
Reprenez le programme de l'exercice 1 et modifiez-le de cette manière afin de renvoyer un résultat.
===== Rendre la fonction paramétrable =====
Il reste maintenant au début du programme un bloc de code, très similaire à celui copié dans le module **saisie()** :
* c’est celui qui concerne la saisie de la valeur à chercher ;
* et la différence est au niveau du **message** qui doit s’afficher.
Voici le bloc de code concerné :
static void Main(string[] args)
{
...
bool correct = false;
// saisie du nombre à chercher
while (!correct) {
try {
Console.Write("Entrez le nombre à chercher = "); // message qui est différent
valeur = int.Parse(Console.ReadLine());
correct = true;
}
...}
Il est possible :
* d’ajouter des **paramètres** à une fonction pour lui envoyer une information ;
* en **ajoutant le paramètre** dans l’entête du module ;
* et ce paramètre est utilisable dans le module comme une **variable locale** :
static int saisie(string message) // -> paramètre avec son type qui peut recevoir une valeur
{
int nombre = 0;
bool correct = false;
while (!correct)
{
try
{
Console.Write(message + " = "); // -> utilisation du paramètre comme une variable locale
nombre = int.Parse(Console.ReadLine());
correct = true;
}
catch
{
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
return nombre;
}
Maintenant, nous pouvons dans le **Main()**, modifier les 3 appels à la fonction **saisie()** pour envoyer une valeur au paramètre.
==== Ajout du paramètre lors de l’appel de la fonction saisie ====
static void Main(string[] args)
{
// déclaration
int valeur = 0, essai = 0, nbre = 1;
// plus de déclaration de la variable correct à faire //bool correct = false;
// saisie du nombre à chercher
valeur = saisie("Entrez le nombre à chercher"); // -> 1er appel de la fonction saisie() avec un message en paramètre
Console.Clear();
// saisie du premier essai
essai = saisie("Entrez un essai"); // -> 2ème appel de la fonction saisie() avec un message en paramètre
// boucle sur les essais
while (essai != valeur)
{
// test de l’essai par rapport à la valeur à chercher
if (essai > valeur) {
Console.WriteLine(" --> trop grand !");
}
else {
Console.WriteLine(" --> trop petit !");
}
// saisie d’un nouvel essai
essai = saisie("Entrez un essai"); // -> 3ème appel de la fonction saisie() avec un message en paramètre
// compteur d’essais
nbre++;
}
// valeur trouvée
Console.WriteLine("Vous avez trouvé en "+nbre+" fois !");
Console.ReadLine();
}
* Les messages d’information **Entrez le nombre à chercher** et **Entrez un essai** sont maintenant transférés dans le paramètre **message** selon les besoins.
La fonction est paramétrée et le code de la fonction **Main()** est nettement plus court.
Dépôt GitHub : https://github.com/ctecher/FonctionC_cor.git
==== Correction ====
[[correction|Correction]]
using System;
class Program
{
static int saisie(string message)
{
bool correct = false;
int chiffre = 0;
while (!correct)
{
try
{
Console.Write(message);
chiffre = int.Parse(Console.ReadLine());
correct = true;
}
catch
{
Console.WriteLine("Erreur de saisie : saisissez un nombre entier");
}
}
return chiffre;
}
public static void Main(string[] args)
{
// déclaration
int valeur = 0, essai = 0, nbre = 1;
// saisie du nombre à chercher
valeur = saisie("Entrez le nombre à chercher = ");
Console.Clear();
// saisie du premier essai
essai = saisie("Entrez un essai = ");
// boucle sur les essais
while (essai != valeur)
{
// test de l’essai par rapport à la valeur à chercher
if (essai > valeur)
{
Console.WriteLine(" --> trop grand !");
}
else
{
Console.WriteLine(" --> trop petit !");
}
// saisie d’un nouvel essai
essai = saisie("Entrez un essai = ");
// compteur d’essais
nbre++;
}
// valeur trouvée
Console.WriteLine("Vous avez trouvé en " + nbre + " fois !");
Console.ReadLine();
}
}
==== Aller plus loin avec plusieurs paramètres ====
Il est possible de mettre plusieurs paramètres à une fonction.
**Exemple :**
static int saisie(string message, int borneMin, int borneMax)