Les structures de sélection : première approche

ifelse.cpp


Les plus curieux d'entre vous ont déjà dû remarquer que nos programmes n'avaient pas grand chose d'interactif. En effet, rien ne venait influer sur le cours du déroulement du programme. Pourtant, c'est une chose essentielle que de réagir en fonction de ce qui se passe ou en fonction de ce que veut l'utilisateur. Nous allons donc remedier à ce manque en voyant aujourd'hui les structures de sélection.

En écrivant le titre de cette page, je me suis rendu compte que les termes "structure de sélection" ont même de quoi faire frémir un technocrate. Ne vous inquiétez pas, il s'agit juste du nom officiel de tout ce qui nous permet de réagir en fonction de ce qui se passe. C'est bien moins austère que ça n'y parait.

Ze if steïtmeunt

Excusez mon accent. L'élément le plus simple et le plus basique de ces structures de sélection, c'est l'instruction if. Notez d'abord qu'il s'agit d'un mot clé.

Imaginez que nous sommes une compagnie d'assurances. Nous voulons inscrire un nouveau client, et il nous faut son age. Si le client est trop vieux (plus de 75 ans), on ne veut pas de lui (c'est dur, le monde des finances :-).

L'idée, c'est de se dire :

Avez-vous remarqué? En anglais, if signifie si (conditionnel). Voyons comment on peut se servir de cette instruction if pour coder ce petit algorithme :

int age;

cout << "Age du client: ";
cin >> age;

if(age >= 75)
{

    cout << "Le client est trop vieux!!!\n";

{

Qu'est-ce qu'on voit? D'abord, l'instruction if est suivie d'une expression logique écrite entre parenthèses. Les parenthèses sont nécessaires, et il faut une expression logique dedans. C'est normal, puisqu'on veut une condition : ici, la condition est que l'age du client soit supérieur ou égal à 75. Si cette condition est remplie (valeur vraie, ou non nulle), alors le bloc d'instruction qui suit l'instruction if est exécuté (et on affiche le très gentil petit message).

Une erreur classique chez le débutant est de se dire : Mais, la condition pour que le client soit accepté est qu'il soit plus jeune que 75 ans. Et là, il a mis la condition inverse!!! C'est mal fait!

Attention : le compilateur n'a absolument aucun moyen de savoir si votre programme est gentil ou méchant, si on compte des carottes ou des tomates, ou si le client est trop vieux pour être assuré chez SnakeSoft Mutuelle Assurance. Dans notre cas de figure, tout ce qu'on veut savoir, c'est si l'âge est supérieur ou égal à 75, car on a prévu quelque chose dans ce cas.

Voici la syntaxe pour utiliser l'instruction if:

if(condition) instruction;

ou alors

if(condition)
{

    instruction1;
    instruction2;
    ...
    instructionX;

}

La première forme ne s'utilise que si on n'a qu'une seule instruction à exécuter dans le if. Sinon, on utilise un bloc d'instructions, avec ses accolades. Rappelez-vous qu'un retour à la ligne n'est pas significatif : souvent, si la première forme est utilisée, vous verrez l'instruction écrite en-dessous de l'instruction if et de sa condition, avec une tabulation. Cette manière d'écrire est plus claire, mais revient exactement au même.

Bien sûr, vous pouvez combiner les expressions logiques :

if((age >= 75) || (age <= 18)) cout << "Le client n'a pas le bon age!\n";

De même, rien ne vous empêche de mettre plusieurs if les uns dans les autres :

if(age >= 75)
{

    cout << "Le client est trop vieux!\n";
    if(taille >= 190) cout << "Et en plus, il est trop grand!\n";

}

Voici un point interessant : l'instruction if et l'instruction ou le bloc d'instruction qui va avec sont considérés en tout comme une seule instruction. Ainsi, on peut écrire :

if(age >= 75)

    if(taille >= 190)

      cout << "Le client est trop grand pour son age!\n";

Il n'y a pas besoin d'accolades pour le premier if, même si le second en avait contenu. Le second if est en effet la seule instruction du premier if. Si age est supérieur à 75, alors on exécute le second if. Si taille est inférieur à 190, alors il ne se passe rien du tout. Evidemment, ici, on aurait pu combiner les deux conditions avec un &&, mais le but était de vous montrer comment utiliser les if imbriqués.

Et sinon, on fait quoi ?

Récapitulons : il est possible de créer un bloc d'instruction qui ne s'exécute que si et seulement si une certaine condition est vraie. Il serait alors un peu décevant de ne pas pouvoir exécuter un bloc d'instruction si et seulement si cette condition n'était pas vraie. Il se peut qu'on doive à un moment ou à un autre n'exécuter qu'un seul bloc sur deux en fonction de la vérité de la condition. Reprenons notre petit algorithme du début du programme, en précisant que si le client n'est pas trop vieux, il est accepté :

En anglais, sinon se dit else. On va donc utiliser le mot clé else :

int age;

cout << "Age du client: ";
cin >> age;

if(age >= 75)

    cout << "Le client est trop vieux!!!\n";

else

    cout << "Le client est acceptable\n";

Dans ce cas-si, si le client n'est pas trop vieux, c'est l'instruction (mais ça aurait pu être un bloc, comme on l'a vu) du else qui est exécuté. On en déduit que s'il y a une instruction if...else... , alors forcément, l'un des deux blocs est exécuté.

Voici la syntaxe pour if...else... :

if(condition)

    instruction ou bloc d'instructions

else

    instruction ou bloc d'instructions

Bien sûr, on ne peut pas avoir un else sans un if préalable, et on ne peut pas les détacher : le else doit venir directement après l'instruction ou le bloc d'instructions du if, sinon c'est une erreur.

L'opérateur conditionnel

Il n'est pas rare de devoir affecter à une variable une valeur qui dépend de la cironstance. Regardez plutôt :

if(y <= 5)

    x = 10;

else

    x = 20;

Dans ce cas-ci, la valeur de x dépend de la condition (y <= 5). Il existe une écriture plus simple de cet exemple :

x = (y <= 5) ? 10 : 20;

On utilise pour cela l'opérateur conditionnel ?: . Voyez l'annexe en question pour plus de détails. Il n'est pas très important (tout de même extrêment pratique) de savoir l'utiliser, mais il faut savoir le reconnaître. Ne confondez pas l'ordre du ? et du :, sinon c'est une erreur.

Encore des if imbriqués!

Revenons à l'époque de notre baccalauréat français (ou du moins à l'époque du mien). On faisait la moyenne de toutes ses notes, et on attribuait la mention en fonction de cette moyenne :

Nous allons coder cet exemple grâce a une série de ifs que nous allons imbriquer, c'est-à-dire mettre les uns dans les autres. Bien sûr, on aurait pu écrire quelque chose comme :

if((moyenne >= 12) && (moyenne < 14)) cout << "Mention Assez Bien\n";

et appliquer comme ceci l'opérateur && pour chaque mention, mais au final, vous verrez que c'est plus fastidieux et moins clair car ça ne reflète pas vraiment l'intention du programme. Regardez-bien, voici le programme du jour :

1
2
3

4
5
6

7

8

9

10

11

12

13

14

15

16

17

#include <iostream.h>
main()
{

    double moyenne;
    cout << "Entrez votre moyenne: ";
    cin >> moyenne;

    if(moyenne >= 16)

      cout << "Mention Très Bien\n";

    else if(moyenne >= 14)

        cout << "Mention Bien\n";

      else if(moyenne >= 12)

          cout << "Mention Assez Bien\n";

        else if(moyenne >= 10)

            cout << "Mention Passable\n";

          else // c'est à dire moyenne < 10

            cout << "Recalé!!!\n";

}

Pour les habitués du BASIC, le else if n'est pas un mot clé, mais bien deux mots clés qui se suivent. Notez que dans le fichier source, j'ai disposé les if...else... un peu différemment, pour que vous compreniez mieux les indentations et pour que vous voyez bien la structure des if imbriqués.

Donc, ce qu'il faut retenir :

  • La structure if permet d'exécuter du code si une condition (sous forme d'expression logique) est remplie (valeur vraie). Si cette condition n'est pas remplie, le code contenu dans l'instruction if est purement et simplement ignoré lors de l'exécution.
  • La structure if...else permet d'exécuter un morceau de code si une condition est remplie (if), et un autre morceau de code si elle ne l'est pas (else). L'un des deux morceaux de code sera forcément exécuté.
  • Dans un programme, chaque else correspond à un if préalable. Le else doit nécessairement suivre le if.
  • Il est tout à fait possible de placer un if à l'intérieur d'un autre. Rappelez-vous que le if n'est qu'une instruction comme une autre, à part qu'on lui ratache une seule instruction ou tout un bloc d'instructions.
  • Si le if n'est rataché qu'à une seule instruction, les accolades ne sont pas nécessaires.
  • Utilisez l'opérateur conditionnel : ça va vous faciliter la vie et raccourcir considérablement vos programmes. De plus, si vous l'utilisez, le lecteur verra tout de suite qu'il s'agit d'une affectation, alors que s'il voit un if...else, il lui faudra lire le contenu pour savoir de quoi il s'agit.

Allons, allons, fini de rigoler, maintenant nous allons faire nos devoirs :

  • Assurez-vous d'avoir bien compris les indentations et la disposition utilisée dans le programme du jour.
  • Pourquoi n'a-t-on pas mis les comparaisons de notes dans l'autre sens, c'est-à-dire en inversant le symbole de comparaison, et en apportant les quelques petites modifications nécessaires? Modifiez le programme pour faire cela, et voyez ce que ça donne. Essayez de comprendre pourquoi, ça vous évitera de nombreux pièges par la suite.
  • Pour voir la différence, réécrivez ce programme en utilisant l'opérateur && pour chaque intervalle de notes. Appréciez la différence d'écriture et de clarté. Au final, c'est votre goût et votre choix qui importe, pas le mien. Rappelez-vous juste que l'écriture proposée ici met en évidence la relation entre les mentions.
  • Ici, on ne vérifie pas que la note est bien comprise en 0 et 20. Ecrivez un petit if...else après la saisie de moyenne qui mette la valeur de celle-ci à 0 si on a entré une valeur inférieure à 0, et à 20 si on a entré une valeur supérieure à 20. Vous aurez souvent ce genre de petites réctifications à faire dans vos programmes.
  • Pourriez-vous réécrire ce if...else en 2 lignes en utilisant l'opérateur conditionnel. Conseil : la première ligne limite la valeur vers le bas, la second limite la valeur vers le haut. De plus, l'une des deux valeurs données avec l'opérateur conditionnel peut être la variable elle-même (dans ce cas-ci, je parle de moyenne). Appréciez la différence avec la structure d'avant.
  • Avec l'opérateur conditionnel, pourriez-vous, sur le même principe, affecter à une variable y la valeur absolue d'une variable x?
    Rappel : la valeur absolue de x, c'est :
    • x si x est positif
    • -x si x est négatif

    La valeur absolue de 10, c'est 10. La valeur absolue de -4, c'est 4.

  • Si la moyenne du baccalauréat est de 18 ou plus, en plus de la mention Très Bien, on reçoit les Félicitations Du Jury. Pourriez-vous rajouter ceci dans le programme. Attention : la mention Très Bien doit quand même figurer dans l'affichage. Attention : il ne s'agit pas de la rajouter à la fin du programme, mais bien dans le if correspondant, il va donc falloir utiliser un bloc d'instructions à cet endroit-là.
  • En sachant qu'on peut aussi utiliser des chaînes de caractères avec l'opérateur conditionnel, comme dans l'exemple qui suit :

      cout << "Il fait " << ((temp >= 20) ? "bon" : "frais") << " ce soir!\n";

    pourriez-vous recoder l'exercice précédent pour utiliser l'opérateur conditionnel dans le if correspondant? Faites comme vous le voulez, l'important c'est que ça marche quand vous testez le programme. Conseil : l'une des deux chaînes de caractères peut être vide ("")!

Au fait, j'espère que mes pages sont présentées convenablement. Si vous avez des suggestions ou des idées, vous savez où me trouver.

La semaine prochaine, nous allons continuer d'explorer un peu les structures de sélection, avec un autre mot clé, et nous allons aborder la notion de constante. Je ne vous dévoile rien de plus pour l'instant...


Voir aussi: l'opérateur conditionnel