• 50 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

course.header.alt.is_certifying

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 30/09/2019

Utilisez les structures de contrôle

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Les programmes doivent être capables de prendre des décisions. Pour y parvenir, les développeurs utilisent ce qu'on appelle des structures de contrôle. Ce nom un peu barbare cache en fait deux éléments que nous verrons dans ce chapitre :

  • les conditions : elles permettent d'écrire dans le programme des règles comme « Si ceci arrive, alors fais cela » ;

  • les boucles : elles permettent de répéter plusieurs fois une série d'instructions.

Savoir manier les structures de contrôle est fondamental ! Bien que ce chapitre ne soit pas réellement difficile, il faut faire attention à bien comprendre ces notions de base. Elles vous serviront durant toute votre vie de développeurs C++ mais aussi dans d'autres langages car le principe y est le même !

Les conditions

Pour qu'un programme soit capable de prendre des décisions, on utilise dans le code source des conditions (on parle aussi de « structures conditionnelles »). Le principe est simple : vous voulez que votre programme réagisse différemment en fonction des circonstances. Nous allons découvrir ici comment utiliser ces fameuses conditions dans nos programmes C++.

Pour commencer, il faut savoir que les conditions permettent de tester des variables. Vous vous souvenez de ces variables stockées en mémoire que nous avons découvertes au chapitre précédent ? Eh bien nous allons maintenant apprendre à les analyser : « Est-ce que cette variable est supérieure à 10 ? », « Est-ce que cette variable contient bien le mot de passe secret ? », etc.

Pour effectuer ces tests, nous utilisons des symboles. Voici le tableau des symboles à connaître par cœur :

Symbole

Signification

==

Est égal à

>

Est supérieur à

<

Est inférieur à

>=

Est supérieur ou égal à

<=

Est inférieur ou égal à

!=

Est différent de

Nous allons utiliser ces symboles pour effectuer des comparaisons dans nos conditions.

Il faut savoir qu'il existe en C++ plusieurs types de conditions pour faire des tests, mais la plus importante, qu'il faut impérativement connaître, est sans aucun doute la condition if.

La conditionif

Comme je vous le disais, les conditions permettent de tester des variables. Je vous propose donc de créer un petit programme en même temps que moi et de faire des tests pour vérifier que vous avez bien compris le principe.

On va commencer avec ce code :

#include <iostream>

using namespace std;

int main()
{
    int nbEnfants(2);

    return 0;
}

Ce code-là ne fait rien pour le moment. Il se contente de déclarer une variablenbEnfants(qui indique donc un nombre d'enfants), puis il s'arrête.

Une première conditionif

Imaginons qu'on souhaite afficher un message de félicitations si la personne a des enfants. On va ajouter une condition qui regarde si le nombre d'enfants est supérieur à 0 et qui, dans ce cas, affiche un message.

#include <iostream>

using namespace std;

int main()
{
    int nbEnfants(2);

    if (nbEnfants > 0)
    {
        cout << "Vous avez des enfants, bravo !" << endl;
    }

    cout << "Fin du programme" << endl;
    return 0;
}

Ce code affiche :

Vous avez des enfants, bravo !
Fin du programme

Regardez bien la ligne suivante :
if (nbEnfants > 0)

Elle effectue le test : « Si le nombre d'enfants est supérieur à 0 » (« if », en anglais, veut dire « si »).
Si ce test est vérifié (donc si la personne a bien des enfants), alors l'ordinateur va lire les lignes qui se trouvent entre les accolades : il va donc afficher le message « Vous avez des enfants, bravo ! ».

Et si la personne n'a pas d'enfants, qu'est-ce qui se passe ?

Dans le cas où le résultat du test est négatif, l'ordinateur ne lit pas les instructions qui se trouvent entre les accolades. Il saute donc à la ligne qui suit la fermeture des accolades.

Dans notre cas, si la personne n'a aucun enfant, on verra seulement ce message apparaître :

Fin du programme

Faites le test ! Changez la valeur de la variablenbEnfants, passez-la à 0 et regardez ce qui se produit.

else: ce qu'il faut faire si la condition n'est pas vérifiée

Vous souhaitez que votre programme fasse quelque chose de précis si la condition n'est pas vérifiée ? C'est vrai que, pour le moment, le programme est plutôt silencieux si vous n'avez pas d'enfant !

Heureusement, vous pouvez utiliser le mot-cléelsequi signifie « sinon ». On va par exemple afficher un autre message si la personne n'a pas d'enfant :

#include <iostream>

using namespace std;

int main()
{
    int nbEnfants(0);

    if (nbEnfants > 0)
    {
        cout << "Vous avez des enfants, bravo !" << endl;
    }
    else
    {
        cout << "Eh bien alors, vous n'avez pas d'enfant ?" << endl;
    }

    cout << "Fin du programme" << endl;
    return 0;
}

Ce code affiche :

Eh bien alors, vous n'avez pas d'enfant ?
Fin du programme

... car j'ai changé la valeur de la variablenbEnfantsau début, regardez bien.
Si vous mettez une valeur supérieure à 0, le message redeviendra celui que nous avons vu avant !

Comment cela fonctionne-t-il ? C'est très simple en fait : l'ordinateur lit d'abord la condition duifet se rend compte que la condition est fausse. Il vérifie si la personne a au moins 1 enfant et ce n'est pas le cas.
L'ordinateur « saute » tout ce qui se trouve entre les premières accolades et tombe sur la ligneelsequi signifie « sinon ». Il effectue donc les actions indiquées après else

Condition if - else
Condition if - else
else if: effectuer un autre test

Il est possible de faire plusieurs tests à la suite. Imaginez qu'on souhaite faire le test suivant :

  • si le nombre d'enfants est égal à 0, afficher ce message « [...] » ;

  • sinon, si le nombre d'enfants est égal à 1, afficher ce message « [...] » ;

  • sinon, si le nombre d'enfants est égal à 2, afficher ce message « [...] » ;

  • sinon, afficher ce message « [...] ».

Pour faire tous ces tests un à un dans l'ordre, on va avoir recours à la conditionelse ifqui signifie « sinon si ». Les tests vont être lus dans l'ordre jusqu'à ce que l'un d'entre eux soit vérifié.

#include <iostream>

using namespace std;

int main()
{
    int nbEnfants(2);

    if (nbEnfants == 0)
    {
        cout << "Eh bien alors, vous n'avez pas d'enfant ?" << endl;
    }
    else if (nbEnfants == 1)
    {
        cout << "Alors, c'est pour quand le deuxieme ?" << endl;
    }
    else if (nbEnfants == 2)
    {
        cout << "Quels beaux enfants vous avez la !" << endl;
    }
    else
    {
        cout << "Bon, il faut arreter de faire des gosses maintenant !" << endl;
    }

    cout << "Fin du programme" << endl;
    return 0;
}

Cela se complique ? Pas tant que cela.

Dans notre cas, nous avons 2 enfants :

  1. L'ordinateur teste d'abord si on en a 0.

  2. Comme ce n'est pas le cas, il passe au premierelse if: est-ce qu'on a 1 enfant ? Non plus !

  3. L'ordinateur teste donc le secondelse if: est-ce qu'on a 2 enfants ? Oui ! Donc on affiche le message « Quels beaux enfants vous avez la ! ».

Si aucune des conditions n'avait été vérifiée, c'est le message du else « Bon, il faut arreter de faire des gosses maintenant ! » qui serait affiché :

Conditions if - else if - else
Conditions if - else if - else

La conditionswitch

En théorie, la conditionifpermet de faire tous les tests que l'on veut. En pratique, il existe d'autres façons de faire des tests. La conditionswitch, par exemple, permet de simplifier l'écriture de conditions qui testent plusieurs valeurs possibles pour une même variable.

Prenez par exemple le test que l'on vient de faire sur le nombre d'enfants :

A-t-il 0 enfant ?
A-t-il 1 enfant ?
A-t-il 2 enfants ?
...

On peut faire ce genre de tests avec desif...else if...else..., mais on peut faire la même chose avec une conditionswitchqui, dans ce genre de cas, a tendance à rendre le code plus lisible. Voici ce que donnerait le code précédent avecswitch:

#include <iostream>

using namespace std;

int main()
{
    int nbEnfants(2);

    switch (nbEnfants)
    {
        case 0:
            cout << "Eh bien alors, vous n'avez pas d'enfant ?" << endl;
            break;

        case 1:
            cout << "Alors, c'est pour quand le deuxieme ?" << endl;
            break;

        case 2:
            cout << "Quels beaux enfants vous avez la !" << endl;
            break;

        default:
            cout << "Bon, il faut arreter de faire des gosses maintenant !" << endl;
            break;
    }

    return 0;
}

Ce qui affiche :

Quels beaux enfants vous avez la !

La forme est un peu différente : on indique d'abord qu'on va analyser la variablenbEnfants(ligne 9). Ensuite, on teste tous les cas (case) possibles : si la variable vaut 0, si elle vaut 1, si elle vaut 2...

Lesbreaksont obligatoires si on veut que l'ordinateur arrête les tests une fois que l'un d'eux a réussi. En pratique, je vous conseille d'en mettre comme moi à la fin de chaquecase.

Enfin, ledefaultà la fin correspond auelse(« sinon ») et s'exécute si aucun des tests précédents n'est vérifié.

Booléens et combinaisons de conditions

Allons un peu plus loin avec les conditions. Nous allons découvrir deux notions plus avancées et néanmoins essentielles : les booléens et les combinaisons de conditions.

Les booléens

Vous vous souvenez du typebool? Ce type de données peut stocker deux valeurs :

  1. true(vrai) ;

  2. false(faux).

Ce type est souvent utilisé avec les conditions. Quand on y pense, c'est logique : une condition est soit vraie, soit fausse. Une variable booléenne aussi.

Si je vous parle du typebool, c'est parce qu'on peut l'utiliser d'une façon un peu particulière dans les conditions. Pour commencer, regardez ce code :

bool adulte(true);

if (adulte == true)
{
    cout << "Vous etes un adulte !" << endl;
}

Cette condition, qui vérifie la valeur de la variableadulte, affiche un message si celle-ci vaut vrai (true).

Vous vous demandez peut-être où je veux en venir ? En fait, il est possible d'omettre la partie «== true» dans la condition, cela revient au même ! Regardez ce code, qui est équivalent :

bool adulte(true);

if (adulte)
{
    cout << "Vous etes un adulte !" << endl;
}

L'ordinateur comprend que vous voulez vérifier si la variable booléenne vauttrue. Il n'est pas nécessaire de rajouter «== true».

Est-ce que cela ne rend pas le code plus difficile à lire ?

Non, au contraire : le code est plus court et plus facile à lire !
if (adulte)se lit tout simplement « S'il est adulte ».

Je vous invite à utiliser cette notation raccourcie quand vous testerez des variables booléennes. Cela vous aidera à clarifier votre code et à rendre certaines conditions plus « digestes » à lire.

Combiner des conditions

Pour les conditions les plus complexes, sachez que vous pouvez faire plusieurs tests au sein d'un seul et mêmeif. Pour cela, il va falloir utiliser de nouveaux symboles :

&&

ET

||

OU

!

NON

Test ET

Imaginons : on veut tester si la personne est adulte et si elle a au moins 1 enfant. On va donc écrire :

if (adulte && nbEnfants >= 1)

Les deux symboles&&signifient « ET ». Notre condition se dirait en français : « Si la personne est adulte ET si le nombre d'enfants est supérieur ou égal à 1 ».

Test OU

Pour faire un OU, on utilise les 2 signes||. Je dois avouer que ce signe n'est pas facilement accessible sur nos claviers. Pour le taper sur un clavier AZERTY français, il faut appuyer sur les touches Alt Gr + 6. Sur un clavier belge, il faut appuyer sur les touches Alt Gr + & et enfin, pour les Suisses, c'est la combinaison Alt Gr + 7 qu'il faut utiliser.

On peut par exemple tester si le nombre d'enfants est égal à 1 OU 2 :

if (nbEnfants == 1 || nbEnfants == 2)
Test NON

Il faut maintenant que je vous présente un dernier symbole : le point d'exclamation. En informatique, le point d'exclamation signifie « Non ».
Vous devez mettre ce signe avant votre condition pour pouvoir dire « Si cela n'est pas vrai » :

if (!adulte)

Cela pourrait se traduire par « Si la personne n'est pas adulte ».

Les boucles

Les boucles vous permettent de répéter les mêmes instructions plusieurs fois dans votre programme. Le principe est représenté en figure suivante.

Une boucle permet de répéter des instructions
  1. l'ordinateur lit les instructions de haut en bas (comme d'habitude) ;

  2. puis, une fois arrivé à la fin de la boucle, il repart à la première instruction ;

  3. il recommence alors à lire les instructions de haut en bas... ;

  4. ... et il repart au début de la boucle.

Les boucles sont répétées tant qu'une condition est vraie. Par exemple on peut faire une boucle qui dit : « Tant que l'utilisateur donne un nombre d'enfants inférieur à 0, redemander le nombre d'enfants ».

Il existe 3 types de boucles à connaître :

  • while;

  • do ... while;

  • for.

La bouclewhile

Cette boucle s'utilise comme ceci :

while (condition)
{
    /* Instructions à répéter */
}

Tout ce qui est entre accolades sera répété tant que la condition est vérifiée.

Essayons de faire ce que j'ai dit plus tôt : on redemande le nombre d'enfants à l'utilisateur tant que celui-ci est inférieur à 0. Ce genre de boucle permet de s'assurer que l'utilisateur rentre un nombre correct.

int main()
{
    int nbEnfants(-1); // Nombre négatif pour pouvoir entrer dans la boucle

    while (nbEnfants < 0)
    {
        cout << "Combien d'enfants avez-vous ?" << endl;
        cin >> nbEnfants;
    }

    cout << "Merci d'avoir indique un nombre d'enfants correct. Vous en avez " << nbEnfants << endl;

    return 0;
}

Voici un exemple d'utilisation de ce programme :

Combien d'enfants avez-vous ?
-3
Combien d'enfants avez-vous ?
-5
Combien d'enfants avez-vous ?
2
Merci d'avoir indique un nombre d'enfants correct. Vous en avez 2

Tant que vous saisissez un nombre négatif, la boucle recommence. En effet, elle testewhile (nbEnfants < 0), c'est-à-dire « Tant que le nombre d'enfants est inférieur à 0 ». Dès que le nombre devient supérieur ou égal à 0, la boucle s'arrête et le programme continue après l'accolade fermante.

La boucledo ... while

Cette boucle est très similaire à la précédente... si ce n'est que la condition n'est testée qu'à la fin. Cela signifie que le contenu de la boucle sera toujours lu au moins une fois.

Cette boucle prend la forme suivante :

do
{
    /* Instructions */
} while (condition);

Notez bien la présence du point-virgule tout à la fin !

Reprenons le code précédent et utilisons cette fois undo ... while:

int main()
{
    int nbEnfants(0);

    do
    {
        cout << "Combien d'enfants avez-vous ?" << endl;
        cin >> nbEnfants;
    } while (nbEnfants < 0);

    cout << "Merci d'avoir indique un nombre d'enfants correct. Vous en avez " << nbEnfants << endl;

    return 0;
}

Le principe est le même, le programme a le même comportement. Le gros intérêt dedo ... whileest qu'on s'assure que la boucle sera lue au moins une fois.
D'ailleurs, du coup, il n'est pas nécessaire d'initialisernbEnfantsà -1 (c'est le principal avantage que procure cette solution). En effet, le nombre d'enfants est initialisé ici à 0 (comme on a l'habitude de faire) et, comme la condition n'est testée qu'après le premier passage de la boucle, les instructions sont bien lues au moins une fois.

La bouclefor

Ce type de boucle, que l'on retrouve fréquemment, permet de condenser :

  • une initialisation ;

  • une condition ;

  • une incrémentation.

Voici sa forme :

for (initialisation ; condition ; incrementation)
{

}

Regardons un exemple concret qui affiche des nombres de 0 à 9 :

int main()
{
    int compteur(0);

    for (compteur = 0 ; compteur < 10 ; compteur++)
    {
        cout << compteur << endl;
    }

    return 0;
}

Ce code affiche :

0
1
2
3
4
5
6
7
8
9

On retrouve sur la ligne duforles 3 instructions que je vous ai indiquées :

  • Une initialisation (compteur = 0) : la variablecompteurest mise à 0 au tout début de la boucle. Notez que cela avait été fait à la ligne immédiatement au-dessus, ce n'était donc pas vraiment nécessaire ici.

  • Une condition (compteur < 10) : on vérifie que la variablecompteurest inférieure à 10 à chaque nouveau tour de boucle.

  • Une incrémentation (compteur++) : à chaque tour de boucle, on ajoute 1 à la variablecompteur! Voilà pourquoi on voit s'afficher à l'écran des nombres de 0 à 9.

Notez qu'il est courant d'initialiser la variable directement à l'intérieur dufor, comme ceci :

int main()
{
    for (int compteur(0) ; compteur < 10 ; compteur++)
    {
        cout << compteur << endl;
    }

    return 0;
}

La variable n'existe alors que pendant la durée de la bouclefor. C'est la forme la plus courante de cette boucle. On ne déclare la variable avant leforque si on en a besoin plus tard, ce qui est un cas assez rare.

En résumé

  • Les conditions permettent de tester la valeur des variables et de modifier le comportement du programme en conséquence.

  • La condition de typeif(si) ...else if(sinon si) ...else(sinon) est la plus courante.

  • La conditionswitch, plus spécifique, permet de tester les différentes valeurs possibles d'une seule variable.

  • Les boucles permettent de répéter les mêmes instructions plusieurs fois.

  • On distingue trois types de boucles :while,do... whileetfor.

  • La boucleforest généralement utilisée lorsqu'on sait combien de fois on souhaite répéter les instructions, tandis quewhileetdo... whilesont plutôt utilisées lorsqu'on souhaite répéter des instructions jusqu'à ce qu'une condition spécifique soit vérifiée.

Exemple de certificat de réussite
Exemple de certificat de réussite