Licence CC 0

Les sélections

Dernière mise à jour :

Comme dit au chapitre précédent, les structures de contrôle permettent de modifier le comportement d’un programme suivant la réalisation de différentes conditions. Parmi ces structures de contrôle se trouvent les instructions de sélection (ou sélections en abrégé) qui vont retenir notre attention dans ce chapitre.

Le tableau ci-dessous reprend celles dont dispose le langage C.

Structure de sélection Action
if… exécute une suite d’instructions si une condition est respectée.
if… else… exécute une suite d’instructions si une condition est respectée ou exécute une autre suite d’instructions si elle ne l’est pas.
switch… exécute une suite d’instructions différente suivant la valeur testée.

La structure if

Vous savez désormais manipuler des conditions, c’est bien, cependant l’intérêt de la chose reste assez limité pour l’instant. Rendons à présent cela plus intéressant en voyant comment exécuter un bloc d’instruction quand une ou plusieurs conditions sont respectées. C’est le rôle de l’instruction if et de ses consœurs.

L’instruction if

L’instruction if permet d’exécuter un bloc d’instructions si une condition est vérifiée ou de le passer si ce n’est pas le cas.

Structure If

L’instruction if ressemble à ceci.

1
2
3
4
if (/* Condition */)
{
    /* Une ou plusieurs instruction(s) */
}

Si la condition n’est pas vérifiée, le bloc d’instructions est passé et le programme recommence immédiatement à la suite du bloc d’instructions délimité par l’instruction if.

Si vous n’avez qu’une seule instruction à réaliser, vous avez la possibilité de ne pas mettre d’accolades.

1
2
if (/* Condition */)
    /* Une seule instruction */

Cependant, nous vous conseillons de mettre les accolades systématiquement afin de vous éviter des problèmes si vous décidez de rajouter des instructions par la suite en oubliant d’ajouter des accolades. Bien sûr, ce n’est qu’un conseil, vous êtes libre de ne pas le suivre.

À présent, voyons quelques exemples d’utilisation.

Exemple 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <stdio.h>


int main(void)
{
    int a = 10;
    int b = 20;

    if (a < b)
    {
        printf("%d est inférieur à %d\n", a, b);
    }

    return 0;
}
1
10 est inférieur à 20

L’instruction if évalue l’expression logique a < b, conclut qu’elle est valide et exécute le bloc d’instructions.

Exemple 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <stdio.h>


int main(void)
{
    int a = 10;
    int b = 20;

    if (a > b)
    {
        printf("%d est supérieur à %d\n", a, b);
    }

    return 0;
}

Ce code n’affiche rien. La condition étant fausse, le bloc contenant l’appel à la fonction printf() est ignoré.

L’instruction else

Avec l’instruction if, nous savons exécuter un bloc d’instructions quand une condition est remplie. Toutefois, si nous souhaitons réaliser une action en cas d’échec de l’évaluation de la condition, nous devons ajouter une autre instruction if à la suite, comme ci-dessous.

1
2
3
4
5
6
7
8
9
if (a > 5)
{
    /* Du code */
}

if (a <= 5)
{
    /* Code alternatif */
}

Le seul problème, c’est qu’il est nécessaire d’ajouter une instruction if et d’évaluer une nouvelle condition, ce qui n’est pas très efficace et assez long à taper. Pour limiter les dégâts, le C fournit une autre instruction : else, qui signifie « sinon ». Celle-ci se place immédiatement après le bloc d’une instruction if et permet d’exécuter un bloc d’instructions alternatif si la condition testée n’est pas vérifiée. Sa syntaxe est la suivante.

1
2
3
4
5
6
7
8
if (/* Condition */)
{
    /* Une ou plusieurs instructions */
}
else
{
    /* Une ou plusieurs instructions */
}

Et elle doit être comprise comme ceci.

Structure if else

Notez que l’instruction else ne possède aucune parenthèse.

Exemple

Supposons que nous voulions créer un programme très simple auquel nous fournissons une heure et qui indique s’il fait jour ou nuit à cette heure-là. Nous supposerons qu’il fait jour de 8 heures à 20 heures et qu’il fait nuit sinon.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
int main(void)
{
    int heure;
    scanf("%d", &heure);

    if (heure > 8 && heure < 20)
    {
        printf("Il fait jour.\n");
    }
    else
    {
        printf("Il fait nuit.\n");
    }

    return 0;
}
1
2
10
Il fait jour.

If / else if

Il est parfois nécessaire d’imbriquer plusieurs instructions if et else les unes dans les autres.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
if (/* Condition */)
{
    /* Du code */
}
else
{
    /* Une ou plusieurs instruction(s) */

    if (/* Autre condition */)
    {
        /* Du code */
    }
}

Cependant, c’est assez long à écrire, d’autant plus s’il y a beaucoup d’imbrications. Pour éviter ces inconvénients, sachez qu’il est possible de combiner une instruction else et une instruction if. Les imbrications simplifiables avec une suite else if sont celles qui s’écrivent comme suit.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
if (/* Expression logique */)
{
    /* Une ou plusieurs instruction(s) */
}
else 
{
    if (/* Expression logique */)
    {
        /* Une ou plusieurs instruction(s) */
    }
}

Faites bien attention : le bloc d’instructions du else doit contenir un if, éventuellement avec un else, mais rien d’autre. Celles-ci peuvent alors être simplifiées comme ceci.

1
2
3
4
5
6
7
8
if (/* Expression logique */)
{
    /* Une ou plusieurs instruction(s) */
}
else if (/* Expression logique */)
{
    /* Une ou plusieurs instruction(s) */
}

Comme vous pouvez le voir, nous avons « fusionné » l’instruction else et la seconde instruction if. Notez que comme il s’agit toujours d’une suite d’instructions if et else, il n’y aura qu’un seul bloc d’instructions qui sera finalement exécuté. En effet, l’ordinateur va tester la condition de l’instruction if, puis, si elle est fausse, celle de l’instruction if suivant l’instuction else et ainsi de suite jusqu’à ce qu’une condition soit vraie (ou jusqu’à une instruction else finale si elles sont toutes fausses).

Notez qu’il n’est pas obligatoire d’ajouter une instruction else.

 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
#include <stdio.h>


int main(void)
{
    int heure = 11;

    if (heure < 7)
    {
        printf("Zzz... \n");
    }
    else if (heure >= 7 && heure < 12)
    {
        printf("C'est le matin !\n");
    }
    else if (heure == 12)
    {
        printf("Il est midi !\n");
    }
    else if (heure > 12 && heure < 18)
    {
        printf("C'est l'après-midi !\n");
    }
    else if (heure >= 18 && heure < 24)
    {
        printf("C'est le soir !\n");
    }
    else if (heure == 24 || heure == 0)
    {
        printf("Il est minuit, dormez brave gens !\n");
    }
    else
    {
        printf("Il est l'heure de réapprendre à lire l'heure !\n");
    }

    return 0;
}
1
2
3
4
5
6
11
On est le matin !
0
Il est minuit, dormez brave gens !
-2
Il est l'heure de réapprendre à lire l'heure !

Exercice

Imaginez que vous avez un score de jeu vidéo sous la main :

  • si le score est strictement inférieur à deux mille, affichez « C’est la catastrophe ! » ;
  • si le score est supérieur ou égal à deux mille et que le score est strictement inférieur à cinq mille, affichez : « Tu peux mieux faire ! » ;
  • si le score est supérieur ou égal à cinq mille et que le score est strictement inférieur à neuf mille, affichez : « Tu es sur la bonne voie ! » ;
  • sinon, affichez : « Tu es le meilleur ! ».

Au boulot ! :)

 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
#include <stdio.h>


int main(void)
{
    int score;

    printf("Quel est le score du joueur ? ");
    scanf("%d", &score);

    if (score < 2000)
    {
        printf("C'est la catastrophe !\n");
    }
    else if (score >= 2000 && score < 5000)
    {
        printf("Tu peux mieux faire !\n");
    }
    else if (score >= 5000 && score < 9000)
    {
        printf("Tu es sur la bonne voie !\n");
    }
    else
    {
        printf("Tu es le meilleur !\n");
    }

    return 0;
}

L'instruction switch

L’instruction switch permet de comparer la valeur d’une variable par rapport à une liste de valeurs. Techniquement, elle permet d’écrire de manière plus concise une suite d’instructions if et else qui auraient pour objectif d’accomplir différentes actions suivant la valeur d’une variable.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
if (a == 1)
{
    /* Instruction(s) */
}
else if (a == 2)
{
    /* Instruction(s) */
}
/* Etc. */
else
{
    /* Instruction(s) */
}

Avec l’instruction switch, cela donne ceci.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
switch (a)
{
case 1:
    /* Instruction(s) */
    break;
case 2:
    /* Instruction(s) */
    break;

/* Etc... */

default: /* Si aucune comparaison n'est juste */
    /* Instruction(s) à exécuter dans ce cas */
    break;
}

Ici, la valeur de la variable a est comparée successivement avec chaque entrée de la liste, indiquées par le mot-clé case. En cas de correspondance, les instructions suivant le mot-clé case sont exécutées jusqu’à rencontrer une instruction break (nous la verrons plus en détail un peu plus tard). Si aucune comparaison n’est bonne, alors ce sont les instructions de l’entrée marquée avec le mot-clé default qui seront exécutées.

Exemple

 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
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>


int main(void)
{
    int note;

    printf("Quelle note as-tu obtenue (sur cinq) ? ");
    scanf("%d", &note);

    switch(note)
    {
    /* si note == 0 */
    case 0:
        printf("No comment.\n");
        break;

    /* si note == 1 */
    case 1:
        printf("Cela te fait 4/20, c'est accablant.\n");
        break;

    /* si note == 2 */   
    case 2:
        printf("On se rapproche de la moyenne, mais ce n'est pas encore ça.\n");
        break;

    /* si note == 3 */
    case 3:
        printf("Tu passes.\n");
        break;

    /* si note == 4*/
    case 4:
        printf("Bon travail, continue ainsi !\n");
        break;

    /* si note == 5 */
    case 5:
        printf("Excellent !\n");
        break;

    /* si note est différente de 0, 1, 2, 3, 4 et 5 */
    default:
        printf("Euh... tu possèdes une note improbable...\n");
        break;
    }

    return 0;
}

Notez que comme pour l’instruction else, une entrée marquée avec le mot-clé default n’est pas obligatoire.

Plusieurs entrées pour une même action

Une même suite d’instructions pour être désignée par plusieurs entrées comme le montre l’exemple suivant.

 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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int main(void)
{
    int note;

    printf("Quelle note as-tu obtenue ? ");
    scanf("%d", &note);

    switch(note)
    {
    /* si la note est comprise entre zéro et trois inclus */
    case 0:
    case 1:
    case 2:
    case 3:
        printf("No comment.\n");
        break;

    /* si la note est comprise entre quatre et sept inclus */
    case 4:
    case 5:
    case 6:
    case 7:
        printf("C'est accablant.\n");
        break;

    /* si la note est comprise entre huit et neuf inclus */  
    case 8:
    case 9:
        printf("On se rapproche de la moyenne, mais ce n'est pas encore ça.\n");
        break;

    /* si la note est comprise entre dix et douze inclus */
    case 10:
    case 11:
    case 12:
        printf("Tu passes.\n");
        break;

    /* si la note est comprise entre treize et seize inclus */
    case 13:
    case 14:
    case 15:
    case 16:
        printf("Bon travail, continue ainsi !\n");
        break;

    /* si la note est comprise entre dix-sept et vingt inclus */
    case 17:
    case 18:
    case 19:
    case 20:
        printf("Excellent !\n");
        break;

    /* si la note est différente */
    default:
        printf("Euh... tu possèdes une note improbable...\n");
        break;
    }

    return 0;
}

Plusieurs entrées sans instruction break

Si vous l’utiliserez souvent, sachez également que l’instruction break n’est pas obligatoire. En effet, le but de cette dernière est de sortir du switch et donc de ne pas exécuter les actions d’autre entrées. Toutefois, il arrive que les actions à réaliser se chevauchent entre entrées auquel cas l’instruction break serait plutôt mal venue.

Prenons un exemple : vous souhaitez réaliser un programme qui affiche entre 1 à dix fois la même phrase, ce nombre étant fourni par l’utilisateur. Vous pourriez écrire une suite de if ou différentes entrées d’un switch qui, suivant le nombre entré, appelleraient une fois printf(), puis deux fois, puis trois fois, etc. mais cela serait horriblement lourd.

Dans un tel cas, une meilleure solution consiste à appeler printf() à chaque entrée du switch, mais de ne pas terminer ces dernières par une instruction break.

 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
39
40
41
42
#include <stdio.h>


int
main(void)
{
    unsigned nb;

    printf("Combien de fois souhaitez-vous répéter l'affichage (entre 1 à 10 fois) ? ");
    scanf("%u", &nb);

    switch (nb)
    {
    case 10:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 9:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 8:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 7:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 6:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 5:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 4:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 3:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 2:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 1:
        printf("Cette phrase est répétée une à dix fois.\n");
    case 0:
        break;
    default:
        printf("Certes, mais encore ?\n");
        break;
    }

    return 0;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Combien de fois souhaitez-vous répéter l'affichage (entre 1 à 10 fois) ? 2
Cette phrase est répétée une à dix fois.
Cette phrase est répétée une à dix fois.

Combien de fois souhaitez-vous répéter l'affichage (entre 1 à 10 fois) ? 5
Cette phrase est répétée une à dix fois.
Cette phrase est répétée une à dix fois.
Cette phrase est répétée une à dix fois.
Cette phrase est répétée une à dix fois.
Cette phrase est répétée une à dix fois.

Comme vous le voyez, la phrase « Cette phrase est répétée une à dix fois » est affichée une à dix fois suivant le nombre initialement fourni. Cela est possible étant donné l’absence d’instruction break entre les case 10 à 1, ce qui fait que l’exécution du switch continue de l’entrée initiale jusqu’au case 0.

L'opérateur conditionnel

L’opérateur conditionnel ou opérateur ternaire est un opérateur particulier dont le résultat dépend de la réalisation d’une condition. Son deuxième nom lui vient du fait qu’il est le seul opérateur du langage C à requérir trois opérandes : une condition et deux expressions.

1
(condition) ? expression si vrai : expression si faux

Les parenthèses entourant la condition ne sont pas obligatoires, mais préférables.

Grosso modo, cet opérateur permet d’écrire de manière condensée une structure if {} else {}. Voyez par vous-mêmes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <stdio.h>

int main(void)
{
    int heure;

    scanf("%d", &heure);

    (heure > 8 && heure < 20) ? printf("Il fait jour.\n") : printf("Il fait nuit.\n");
    return 0;
}

Il est également possible de l’écrire sur plusieurs lignes, même si cette pratique est moins courante.

1
2
3
(heure > 8 && heure < 20)
    ? printf("Il fait jour.\n")
    : printf("Il fait nuit.\n");

Cet opérateur peut sembler inutile de prime abord, mais il s’avère être un allié de choix pour simplifier votre code quand celui-ci requiert la vérification de conditions simples.

Exercice

Pour bien comprendre cette nouvelle notion, nous allons faire un petit exercice. Imaginez que nous voulions faire un mini jeu vidéo dans lequel nous affichons le nombre de coups du joueur. Seulement voilà, vous êtes maniaques du français et vous ne supportez pas qu’il y ait un « s » en trop ou en moins. Essayez de réaliser un programme qui demande à l’utilisateur d’entrer un nombre de coups puis qui affiche celui-ci correctement accordé.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <stdio.h>

int main(void)
{
    int nb_coups;

    printf("Donnez le nombre de coups : ");
    scanf("%d", &nb_coups);
    printf("Vous gagnez en %d coup%c\n", nb_coups, (nb_coups > 1) ? 's' : ' ');
    return 0;
}

Ce programme utilise l’opérateur conditionnel pour condenser l’expression et aller plus vite dans l’écriture du code. Sans lui nous aurions dû écrire quelque chose comme ceci.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <stdio.h>

int main(void)
{
    int nb_coups;

    printf("Donnez le nombre de coups : ");
    scanf("%d", &nb_coups);

    if (nb_coups > 1)
        printf("Vous gagnez en %d coups\n", nb_coups);
    else
        printf("Vous gagnez en %d coup\n", nb_coups);

    return 0;
}

Ce chapitre a été important, il vous a permis d’utiliser les conditions ; les instructions if et else ; l’instruction switch et l’opérateur conditionnel. Aussi, si vous n’avez pas très bien compris ou que vous n’avez pas tout retenu, nous vous conseillons de relire ce chapitre.

Le chapitre suivant sera l’occasion de mettre en œuvre ce que vous avez appris puisqu’il s’agira de votre premier TP.