Jeux Libres
       
           

» Les Tutoriels » Apprenez à programmer en C++ ! » Les structures de contrôle

Note : Vous vous apprêtez à lire un tutoriel de M@teo21 et Nanoc initialement publié à cette adresse sous la licence Creative Commons BY-NC-SA 2.0.

Les structures de contrôle


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 une série d'instructions plusieurs fois.

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 !

Ces outils sont en fait exactement les mêmes en C++ qu'en C. Si vous avez déjà programmé en C, vous ne devriez donc pas être dépaysés.
Et si vous n'avez jamais fait de C de votre vie, ce n'est pas grave, nous allons tout apprendre dans ce chapitre. ;)





Chapitre précédent     Sommaire     Chapitre suivant


Les conditions


Pour qu'un programme soit capable de prendre des décisions, on utilise des conditions dans le code source (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 ? 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 ?"...

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

SymboleSignification
==Est égal à
>Est supérieur à
<Est inférieur à
>=Est supérieur ou égal à
<=Est inférieur ou égal à
!=Est différent de

Faites très attention, il y a bien 2 symboles "=" pour tester l'égalité. Les débutants oublient souvent cela et n'écrivent qu'un seul "=", ce qui n'a pas la même signification en C++.


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

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

La condition if



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 :
1
2
3
4
5
6
7
8
9
10
#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 variable nbEnfants (qui indique un nombre d'enfants donc), puis il s'arrête.

Une première condition if



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 affiche un message dans ce cas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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 :
1
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 test n'est pas vérifié, l'ordinateur ne lit pas les instructions qui se trouvent entre 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 variable nbEnfants, mettez-la à 0, et regardez ce qui se passe. :)

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'enfants !

Heureusement, vous pouvez utiliser le mot-clé else qui signifie "sinon". On va par exemple afficher un autre message si la personne n'a pas d'enfants :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#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'enfants ?" << endl;
   }
 
   cout << "Fin du programme" << endl;
   return 0;
}

Ce code affiche :
Eh bien alors, vous n'avez pas d'enfants ?
Fin du programme

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

Bien, comment ça fonctionne ? C'est très simple en fait : l'ordinateur lit d'abord la condition du if et se rend compte que la condition est fausse. On 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 ligne du else qui signifie "sinon". Il effectue donc les actions indiquées après le 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 condition else if qui signifie "sinon si". Les tests vont être lus dans l'ordre jusqu'à ce que l'un d'entre eux soit vérifié.
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
#include <iostream>
 
using namespace std;
 
int main()
{
   int nbEnfants(2);
 
   if (nbEnfants == 0)
   {
       cout << "Eh bien alors, vous n'avez pas d'enfants ?" << 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;
}

Ça se complique ? Pas tant que ça. ;)

Dans notre cas, nous avons 2 enfants :

  • L'ordinateur teste d'abord si on en a 0.
  • Comme ce n'est pas le cas, il passe au premier else if : est-ce qu'on a 1 enfant ? Non plus !
  • L'ordinateur teste donc le second else 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 se serait affiché.


La condition switch



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

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

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

On peut faire ce genre de tests avec des if ... else if ... else, mais on peut faire la même chose avec une condition switch qui a tendance à rendre le code plus lisible dans ce genre de cas. Voici ce que donnerait la condition précédente avec un switch :
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 <iostream>
 
using namespace std;
 
int main()
{
   int nbEnfants(2);
 
   switch (nbEnfants)
   {
       case 0:
           cout << "Eh bien alors, vous n'avez pas d'enfants ?" << 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;
}

Cela affiche :
Quels beaux enfants vous avez la !

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

Les break sont obligatoires si on veut que l'ordinateur ne continue pas d'autres tests une fois qu'il en a vérifié un. En pratique, je vous conseille d'en mettre toujours comme moi à la fin de chaque case.

Enfin, le default à la fin correspond au else ("sinon") et s'exécute si aucun test précédent n'est vérifié.

Le switch ne permet de tester que l'égalité. Vous ne pouvez pas tester "Si le nombre d'enfants est supérieur à 2" avec un switch : il faut utiliser un if dans ce cas.
De plus, le switch ne peut tester que des nombres entiers ( int, unsigned int, char ). Il est impossible de tester des nombreux décimaux ( double ) avec un switch.

Le switch est donc limité en terme de possibilités mais il permet d'utiliser une écriture alternative qui peut être parfois pratique dans des cas simples.


Les ternaires



Les ternaires sont un autre type de condition très... condensée. On les utilise peu, mais vous en verrez probablement un jour donc il vaut mieux vous les présenter. ;)

Prenez ce code :
1
2
3
4
5
6
7
8
9
10
11
int nbEnfants(2);
bool parent(false);
 
if (nbEnfants > 0)
{
   parent = true;
}
else
{
   parent = false;
}

Son fonctionnement est simple :

  • Si le nombre d'enfants est supérieur à 0, on met la variable booléenne "parent" à true (vrai).
  • Sinon, on met "parent" à false (faux).

Dans un cas comme celui-ci où on fait un test et où on change la valeur d'une variable, on pourrait utiliser une forme ternaire.
Voici le même code que précédemment... mais en beaucoup beaucoup plus court !
1
2
3
4
int nbEnfants(2);
bool parent(false);
 
parent = (nbEnfants > 0) ? true : false;

La ligne se lit à partir de nbEnfants : est-ce que le nombre d'enfants est supérieur à 0 ? Si oui, on met true dans la variable parent (tout à gauche), si non on met false.

Ouah c'est compliqué ! Est-ce que je dois vraiment connaître ça ? :o


Non, rassurez-vous, je vous présente cette méthode mais nous n'allons pas vraiment l'utiliser... d'autant plus qu'on peut faire la même chose avec if ! Sachez juste que ça existe au cas où vous en rencontriez un jour dans un code. ;)


Booléens et combinaisons de conditions


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

Les booléens



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

  • true (vrai)
  • 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 type bool, c'est parce qu'on peut l'utiliser d'une façon un peu particulière dans les conditions. Regardez ce code pour commencer :
1
2
3
4
5
6
bool adulte(true);
 
if (adulte == true)
{
   cout << "Vous etes un adulte !" << endl;
}

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

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 :
1
2
3
4
5
6
bool adulte(true);
 
if (adulte)
{
   cout << "Vous etes un adulte !" << endl;
}

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

Ça ne rend pas le code plus difficile à lire ça ? :o


Non, au contraire le code est plus court et plus facile à lire !
La ligne 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ême if. Pour cela, il va falloir utiliser de nouveaux symboles :

&&ET
||OU
!NON

Test ET



Imaginons : on veut faire tester si la personne est adulte ET si elle a 1 enfant au moins. On va écrire :
1
if (adulte && nbEnfants >= 1)

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

Notez que j'aurais aussi pu écrire cette condition comme ceci : if (adulte == true && nbEnfants >= 1)
Cependant, comme je vous l'ai expliqué un peu plus tôt, il est facultatif de préciser "== true" sur les booléens et c'est une habitude que je vous invite à prendre.


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 faudra faire
Alt Gr
+
6
. Sur un clavier belge, il faudra faire
Alt Gr
+
&
et finalement, 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 :
1
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" :
1
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 le suivant :


  • L'ordinateur lit les instructions de haut en bas (comme d'habitude)
  • Puis, une fois arrivé à la fin de la boucle, il repart à la première instruction
  • Il recommence alors à lire les instructions de haut en bas...
  • ... 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

Contrairement aux conditions, les 3 sont assez fréquemment utilisées (le for étant sensiblement plus utilisé).

La boucle while



Cette boucle s'utilise comme ceci :
1
2
3
4
while (condition)
{
   /* Instructions rpter */
}

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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
   int nbEnfants(-1); // Nombre ngatif pour pouvoir rentrer 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 mettrez un nombre négatif, la boucle recommencera. En effet, elle teste while (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.

Vous noterez que j'ai initialisé la variable nbEnfants à -1. En effet, pour que l'ordinateur veuille bien rentrer une première fois dans la boucle, il faut faire en sorte que la condition soit vraie la première fois. ;)


La boucle do ... while



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

Cette boucle a cette forme :
1
2
3
4
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 un do ... while :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 du do ... while est qu'on s'assure que la boucle sera lue au moins une fois.
D'ailleurs, du coup, il n'est pas nécessaire d'initialiser nbEnfants à -1 (c'est le principal avantage que procure cette solution). En effet, ici le nombre d'enfants est initialisé à 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 boucle for



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

  • Une initialisation
  • Une condition
  • Une incrémentation

Voici sa forme :
1
2
3
4
for (initialisation ; condition ; incrementation)
{
 
}

Regardons un exemple concret qui affiche des nombres de 0 à 10 :
1
2
3
4
5
6
7
8
9
10
11
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
10

On retrouve sur la ligne du for les 3 instructions que je vous ai indiquées :

  • Une initialisation (compteur = 0) : la variable compteur est mise à 0 au tout début de la boucle. Notez que ça avait été fait juste la ligne au-dessus donc ce n'était pas vraiment nécessaire ici.
  • Une condition (compteur <= 10) : on vérifie que la variable compteur ne dépasse pas 10 à chaque nouveau tour de boucle.
  • Une incrémentation (compteur++) : à chaque tour de boucle, on ajoute 1 à la variable compteur ! Voilà pourquoi on voit s'afficher à l'écran des nombres de 0 à 10. :)

Vous pouvez faire autre chose qu'une incrémentation si vous le désirez. La dernière section du for est réservée à la modification de la variable et vous pouvez donc y faire une décrémentation (compteur--) ou avancer de 2 en 2 (compteur += 2), etc.

Notez qu'il est courant de déclarer la variable directement à l'intérieur du for, comme ceci :
1
2
3
4
5
6
7
8
9
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 boucle for.

Quand utiliser un for et quand utiliser un while ?
On utilise la boucle for quand on connaît le nombre de fois que l'on souhaite boucler, et on utilise le plus souvent la boucle while quand on ne sait pas combien de fois la boucle va être effectuée.




Vous savez maintenant manier les structures de contrôle, ces éléments indispensables à tous les programmes informatiques ! :)

Prenez le temps de vous approprier les codes présentés dans ce chapitre car nous allons utiliser des conditions et des boucles tout au long de ce cours !



Chapitre précédent     Sommaire     Chapitre suivant



Distribué et adapté par David
Consulté 10740 fois



Hébergeur du site : David
Version PHP : 5.4.45-0+deb7u2
Uptime : 240 jours 12 heures 17 minutes
Espace libre : 1569 Mo
Dernière sauvegarde : 22/07/2019
Taille de la sauvegarde : 1112 Mo


5357232 pages ont été consultées sur le site !
Dont 2695 pages pendant les 24 dernières heures.

Page générée en 0.594 secondes


Nos sites préférés
- Création d'un jeu de plateforme de A à Z avec SDL
- Zelda ROTH : Jeux amateurs sur le thème de Zelda
- Zeste de Savoir : la connaissance pour tous et sans pépins
- YunoHost : s'héberger soi-même en toute simplicité
- Site de Fvirtman : recueil de projets et de codes en C et C++
- Par ici la sortie : le site des idées de sorties


  © 2005-2019 linor.fr - Toute reproduction totale ou partielle du contenu de ce site est strictement interdite.