Nous avons vu comment se déroulait un programme et comment déclarer des variables. Cependant, nos programmes s'effectuent encore de façon linéaire : les instructions sont alignées les unes en dessous des autres sans que le programme ait la possibilité de s'adapter au contexte.
Dans ce chapitre, nous verrons comment faire en sorte de rendre notre programme dynamique, c'est-à-dire susceptible de varier en fonction d'un cas d'utilisation. Tout cela grâce aux branchements conditionnels. Let's go !
Les branchements conditionnels en programmation
Introduction
Jusqu'ici, nos programmes s'exécutaient de façon linéaire et sans possibilité d'adapter le code exécuté, de le rendre dynamique. C'est pourtant l'essence même d'un bon programme : s'adapter à une demande. Les branchements conditionnels constituent une solution simple et hautement répandue dans le monde de la programmation.
Principe
L'idée des branchements conditionnels est très simple : exécuter tel code source si telle chose est vraie, sinon faire autre chose. Ils permettent à un programme de suivre plusieurs chemins différents à partir d'un même code source.
La cuisine, encore et toujours
Prenez cette recette de cuisine par exemple :
// Cuisson d'un œuf
prenez un œuf
faites chauffer de l'eau
mettez l'oeuf dans l'eau
si vous aimez les oeufs à la coque
faites cuire 3 minutes
servez dans un coquetier
sinon si vous aimez les oeufs mollet
faites cuire 4 minutes trente
enlevez la coquille
servez en salade
sinon si vous aimez les oeufs durs
faites cuire 6 minutes
enlevez la coquille
coupez l'oeuf en deux
mettez une noix de mayonnaise sur chacune des moitiés
Dans cette recette de cuisine, nous adaptons le processus de cuisson et de dégustation au goût de l'utilisateur. Ainsi, bien que toutes les instructions soient écrites, seules celles qui correspondent au choix de l'utilisateur seront à exécuter. Eh bien, c'est exactement ce même principe qui est repris en programmation !
Les branchements conditionnels côté C# : If et else
Les structures si... sinon...
Côté C#, la mise en place de ces branchements conditionnels est simple. Nous avons à notre disposition deux mots-clé permettant d'introduire des conditions : If et else qui signifient respectivement si et sinon.
Ces mots-clé introduisent des conditions qui, si elles sont respectées, donneront lieu à l'exécution d'une portion de code. Voyons tout cela au travers d'un exemple.
Majeur ou mineur
Dans cet exemple, nous allons créer un programme tout bête qui demande son âge à l'utilisateur, lui affiche un message de bienvenue si il est majeur et le rejette si il est mineur.
Code préparatoire
Pour cela, nous devoir être en mesure de demander quelque chose à l'utilisateur. Dans un programme en mode console, nous utiliserons
Console.ReadLine()
pour demander quelque chose à l'utilisateur et récupérer le résultat au sein d'une variable. Créez et initialisez un projet C# intitulé MajeurMineur. Nous y placerons le code suivant :
static void Main(string[] args)
{
Console.WriteLine("Quel âge avez-vous ?");
string reponseUtilisateur = Console.ReadLine();
}
Ceci est le petit bout de code que nous placerons au début de notre programme afin de demander son âge à l'utilisateur et de récupérer la réponse dans une variable appelée reponseUtilisateur, qui est une chaine de caractère (string). Pour pouvoir déterminer si l'âge de l'utilisateur est supérieur à 18, nous allons devoir convertir cette variable en un entier. Pour cela, nous allons utiliser ce code :
int age = Int32.Parse(reponseUtilisateur);
Cette ligne va essayer de convertir la réponse de l'utilisateur en entier. Si la réponse n'est pas un entier, le programme déclenchera une erreur et quittera. Sinon, la variable age contiendra un entier et le programme continuera.
On se branche
Nous allons maintenant entrer dans le vif du sujet en créant notre premier branchement conditionnel. Notre programme vérifiera si âge est inférieur à 18. Si c'est le cas, il demandera à l'utilisateur de déguerpir, sinon, il lui affichera un message de bienvenue.
Voici la forme que prend la suite de notre programme en C#.
if (age < 18) { // vérification de la variable age
// cette ligne n'est exécutée que si age est inférieur à 18
Console.WriteLine("Vous êtes mineur. Du balai !");
} else {
// cette ligne n'est exécutée que si age est supérieur à 18
Console.WriteLine("Vous êtes majeur. Bienvenue !");
}
Récapitulons :
Nous avons ce qu'on appelle une condition, cette condition est entourée de parenthèses et introduite par le mot-clé if. Ensuite nous avons une accolade ouvrante {, laquelle marque le début d'un bloc de code qui ne sera exécuté que si la condition entre les parenthèse est vraie. C'est-à-dire, dans notre cas si age est inférieur à 18. Ce bloc de code est refermé plus loin par une accolade fermante }.
Ensuite, nous avons le mot-clé else qui introduit la code à exécuter si la condition du if est fausse. Ce code alternatif est lui aussi contenu dans des accolades { }.
Si on exécute ce code, on obtient les résultats suivant :
ou bien
En fonction de la valeur entrée par l'utilisateur, le code exécuté change. Ça n'a l'air de rien mais le branchement conditionnel est l'un des principes les plus importants de la programmation. Cela dit, nous n'avons ici branché que deux codes. Il est possible de brancher plusieurs codes les uns à la suite des autres en effectuant plusieurs branchements à la suite. Voyons cela.
Les structures si... sinon si... sinon
Pour brancher plusieurs codes et pas seulement deux, on utilise une structure if... else if... else.
Pour mettre cette notion en évidence, créons un petit projet console nommé Appreciations. Ce projet donnera une appréciation en fonction d'une note sur 10 entrée par l'utilisateur (Bien, Pas bien, Super bien etc.)
Voici ce que cela donne :
static void Main(string[] args)
{
Console.Write("Entrez un note sur 10 : ");
String reponse = Console.ReadLine();
int note = Int32.Parse(reponse);
if(note < 0) {
Console.WriteLine("Une note négative ? Ah ! c'est une dictée. Bon d'accord.");
} else if(note <= 3) {
Console.WriteLine("Bof ! Bof !");
} else if(note <= 5) {
Console.WriteLine("Peut mieux faire.");
} else if(note <= 7) {
Console.WriteLine("Bien !");
} else if(note <= 10) {
Console.WriteLine("Trop la classe !");
} else {
Console.WriteLine("Une note sur 10, j'ai dit.");
}
}
La structure est la suivante : on commence par un if, puis on passe au else if, puis on ajoute des conditions les unes à la suite des autres à l'aide de else if successifs.
Dans cet exemple, vous voyez que les conditions sont mutuellement excluantes, c'est-à-dire que si l'une d'elles est vraie, seul le code associé s'exécute. Si aucune condition n'est vérifiée, c'est le else qui s'exécute.
Gardez à l'esprit que tout branchement conditionnel soit nécessairement commencer par un if mais ne se termine pas obligatoirement par un else. Il est même possible d'écrire des branchements conditionnels avec un seul code, lequel ne sera exécuté que si une condition est vraie :
Console.Write("Entrez un note sur 10 : ");
String reponse = Console.ReadLine();
int note = Int32.Parse(reponse);
if(note < 0) {
Console.WriteLine("Une note négative ? Ah ! c'est une dictée. Bon d'accord.");
}
if(note <= 3) {
Console.WriteLine("Bof ! Bof !");
} else if(note <= 5) {
//...
Dans ce code, si la note est inférieure à 0, deux messages s'afficheront, celui concernant la dictée et "Bof ! Bof"
La structure switch
Exemple
Il existe une autre manière de créer des branchements conditionnels. Celle-ci est plus rare mais peut s'avérer utile. Il s'agit de la structure switch. Son écriture est un peu plus complexe mais peut rendre plus lisible certaines conditions, c'est pourquoi on la préfère parfois aux branchements if... else.
Reprenons l'exemple précédent à l'aide d'une structure switch :
static void Main(string[] args)
{
Console.Write("Veuillez entrer une note");
string reponse = Console.ReadLine();
int note = Int32.Parse(reponse);
switch(note) {
case 0 :
case 1 :
case 2 :
case 3 :
Console.WriteLine("Bof ! Bof !");
break;
case 4 :
case 5 :
Console.WriteLine("Peut mieux faire.");
break;
case 6 :
case 7 :
Console.WriteLine("Bien !");
break;
case 8 :
case 9 :
case 10 :
Console.WriteLine("Trop la classe :");
break;
default :
Console.WriteLine("Une note sur 10, j'ai dit.");
break;
}
}
Dans cette structure, on teste une à une les valeurs possibles d'une même variable. On place cette variable entre les parenthèses qui suivent le mot-clé switch. Des accolades { } viennent ensuite entourer la liste des cas (case en anglais). Chaque cas correspond en fait à une valeur à tester. On peut choisir d'exécuter des codes communs à plusieurs valeurs en enchainant les cas comme dans l'exemple (0,1,2,3 puis 4,5 puis 6,7 puis 8,9 et 10. Le mot-clé break permet de rompre l'enchainement des cas. Ainsi, si un cas se produit avant un break, le code situé après le break ne sera pas exécuté.
Par exemple : si note est égal à 4, aucun des 5 premiers cas ne se produit. Le code situé avant le sixième cas ne s'exécute pas. Le sixième cas est en revanche vrai et le code s'exécute jusqu'au premier break rencontré.
Limites de la structure switch
Notez que cet exemple ne fonctionne pas exactement comme le code basé sur la structure if... else if. L'avantage du if... else if est qu'il permet de gérer des conditions complexes (comme l'inégalité note < 0) alors que switch ne permet de tester que des ensembles de valeurs. Notre dernier code gère donc assez mal le cas des valeurs négatives.
On utilise de préférence switch lorsque on teste un ensemble déterminé de valeur et à plus forte raison lorsque certaines de ces valeurs peuvent donner lieu l'exécution de codes communs.
Dans tous les autres cas, ce sera if... else !
Les booléens : le terrible secret des conditions
Vous avez vu que nous pouvions mettre des conditions dans nos structures conditionnelles. En réalité, ces conditions sont des types de variable bien particuliers : les booléens. Ceux-ci peuvent prendre uniquement deux valeurs true ou false (vrai ou faux). Gardez donc bien à l'esprit que ces conditions doivent toujours être des booléens.
Conclusion
Les branchements conditionnels constituent un des fondamentaux permettant d'adapter un programme à un cas d'utilisation. Avec les boucles, elles constituent la base du fonctionnement de langages impératifs tels que C#. Si la structure if est la plus utilisée et la plus puissante, il est bon de connaître et de savoir utiliser la structure switch quand cela est pertinent.