Logo de SAASF

I - 3. Utiliser des conditions

L'utilisation de variable permet de faire pleins de choses, mais reste néanmoins limité. En effet, vous ne pouvez pas adapter l'utilisation du programme selon des variables / données prédéfinies. Sans cela, votre programme n'est pas très utile. Heuresement, cela est possible en C++, et nous allons voir comment dés maintenant.
Contenu

A. Conditionner son programme

Pour commencer, nous allons définir ce qu'est le conditionnement d'un programme, et son utilité.

a. Que ce qu'est une condition ?

Par définition, une condition est "État, situation, fait dont l'existence est indispensable pour qu'un autre état, un autre fait existe", selon le Robert. En programmation, dans notre contexte nécessaire, une condition est une question que l'on pose au processeur, qui peut avoir pour réponse "vrai" ou "faux", et qui permet de faire quelque chose selon la réponse du processeur. Comme nous allons poser la condition au processeur, il est important de noter que l'obstention d'un résultat se fait via des instructions, que nous verrons juste après. La condition en elle même est, souvent, présente dans le code source d'un programme.

Cette définition peut, dans un certain sens, nous rappeler la définition des données, voir des variables, pour de bonnes raisons. En effet, le résultat d'une condition est une donnée, qui peut avoir pour valeur soit "vrai" soit "faux". Elle peut donc être utilisée de manière similaire à une donnée : lecture, modification...

Nous avons vu plus tôt que l'obstention d'un résultat se fait via des instructions. En théorie, toute question peut être considérée comme une condition. Cependant, d'un point de vue bas niveau informatique, les conditions sont souvent des comparaisons, via des comparateurs. Des exemples de comparaison sont "plus petit que", "plus grand que", "égal à" ou "différent de". En assembleur X86, cela se fait avec l'instruction "CMP". Cela marche avec des nombres, et donc, comme nous l'avons vus dans les derniers cours, avec tout ce qui utilisent des nombres (caractères ASCII...).

De plus, ayant seulement deux valeurs possibles, les résultats de conditions peuvent aussi être utilisées avec l'algèbre de Boole. Cette algèbre permet l'utilisation de plusieurs comparateurs très utiles, entre deux résultats de conditions. Les trois comparateurs de ce genre les plus importants sont ET, OU et NON. ET permet de savoir si deux résultats de conditions sont vraies, OU si au moins un des résultats de conditions est vraie, et NON si un résultats de condition n'est pas vraie. Ces comparateurs extrêmement basiques permettent de faire des comparateurs un peu plus complexes, comme XOR (ou exclusif, un seul résultat de condition vraie), ou "plus grand ou égal" (plus grand ou égal ¯\_(ツ)_/¯).

Pour utiliser correctement les conditions, il ne faut pas avoir peur d'en mettre plusieurs à côté. Pour cela, il est conseillé d'utiliser des parenthèses entre chaque condition, pour ne pas créer de contextes ambigüs. Par exemple, voici une condition en pseudo-code bien formulée, sous forme de variable :

a_le_bac = moyenne > 10 ou (a_ete_au_rattrapage et moyenne_rattrapage > 10)
Par contre, une mauvaise pratique serait d'écrire :
a_le_bac = moyenne > 10 ou a_ete_au_rattrapage et moyenne_rattrapage > 10
Parce que, comme ça, on peut lire soit :
a_le_bac = moyenne > 10 ou (a_ete_au_rattrapage et moyenne_rattrapage > 10)
Soit :
a_le_bac = (moyenne > 10 ou a_ete_au_rattrapage) et moyenne_rattrapage > 10
Les deux ayant des sens bien différents. Il faut donc faire attention à bien structurer sa condition.

b. Comment changer son programme selon une condition ?

Pour l'instant, nous avons vu une version des conditions très proche des variables. Cependant, cette utilisation ne permet pas grand chose, appart de savoir si une condition est vraie ou fausse, sans que cela n'influe quoi que ce soit dans le programme. Pour pouvoir modifier le comportement du programme selon une condition, il faut utiliser quelque chose d'essentiel en programmation : les structures de conditions. Elles permettent de faire certaines choses, ou non, selon la valeur d'une condition.

La structure de condition la plus connues est "SI". D'un point de vue assez haut niveau, elle peut se traduire par "SI une condition est vraie, faire quelque chose". Si la condition n'est pas vraie, alors cette chose ne sera pas faite. Voici un petit exemple de pseudo-code, utilisant "SI" :

demander l'age à l'utilisateur
si age est plus grand ou égal à 18, afficher "Vous êtes majeur."
Elle permet de commencer à modifier le programme directement dans le code source, selon ce qu'il se passe pendant l'exécution.

Avec cette condition seule, nous pouvons faire quelque chose si une condition est vraie. Cependant, si elle est fausse, on ne peut pas faire autre chose, directement via cette condition. En théorie, on pourrait rajouter juste après "SI la condition est fausse", et cela fonctionnerait. Cependant, c'est assez moche. Heuresement, il y a une autre structure, "SINON", qui, rajoutée après un "SI", permet de dire au programme que faire si la condition est fausse. D'un point de vue assez haut niveau, elle peut se traduire par "SI une condition est vraie, faire quelque chose, SINON, faire autre chose". Voici un petit exemple de pseudo-code, utilisant "SINON" :

demander l'age à l'utilisateur
si age est plus grand ou égal à 18, afficher "Vous êtes majeur." sinon, afficher "Vous êtes mineur."

Si plusieurs conditions doivent être testées, il est possible de combiner les deux structures pour en faire une dernière. En fait, la struct "SINON SI" représente une structure "SINON", mais qui a besoin d'une autre condition pour passer. D'un point de vue assez haut niveau, elle peut se traduire par "SI une condition est vraie, faire quelque chose, SINON SI une autre condition est vraie, faire autre chose". Vous pouvez aussi rajouter un "SINON" après un (ou plusieurs) "SINON SI". Voici un petit exemple de pseudo-code, utilisant "SINON SI" :

demander l'age à l'utilisateur
si age est plus grand ou égal à 60, afficher "Vous êtes un boomer."
sinon, si age est plus grand ou égal à 44, afficher "Vous êtes un gen X."
sinon, si age est plus grand ou égal à 24, afficher "Vous êtes un gen Y."
sinon, si age est plus grand ou égal à 10, afficher "Vous êtes un gen Z."
sinon, afficher "Vous êtes un gen Alpha."

De manière très similaire à la structure "SINON SI", il est possible d'utiliser une autre structure pour tester plusieurs conditions. Il s'agit de la structure "SELON", qui prend une donnée, et y applique plusieurs conditions. D'un point de vue assez haut niveau, elle peut se traduire par "SELON une donnée, SI une condition avec cette donnée est vraie, faire quelque chose chose, SINON SI une autre condition avec cette donnée est vraie, faire autre chose, SINON, faire autre chose". C'est une forme simplifiée pour remplacer plein de "SINON SI". Pour notre exemple plus haut, cela donnerait :

demander l'age à l'utilisateur
selon age
--- si age est plus grand ou égal à 60, afficher "Vous êtes un boomer."
--- sinon, si age est plus grand ou égal à 44, afficher "Vous êtes un gen X."
--- sinon, si age est plus grand ou égal à 24, afficher "Vous êtes un gen Y."
--- sinon, si age est plus grand ou égal à 10, afficher "Vous êtes un gen Z."
--- sinon, afficher "Vous êtes un gen Alpha."

Une dernière chose à noter, est que, en pseudo-code, il y a souvent un petit mot présent, que je n'ai pas mis ici. Il s'agit de "FIN SI". Il permet de connaître la fin de la structure de conditions qu'il succède. Je ne l'ai pas mis car je considère que toute la partie, soit sur la même ligne que SI, soit indenté après SI, est dans la structure. Indenté veut dire toute la partie après le SI, qui est espacée de la gauche de l'écran d'un certain nombre de caractères. Dans mon exemple de en haut, toute la partie indentée est la partie avec des "--- " devant. Le nombre de "-" représente l'indentation, en général (dans ce cas), un multiple de 4 moins 1 "-". J'ai donc pris la décision de ne pas le mettre, bien que je pourrai le mettre, et qu'il est parfois recommandé de le mettre.

c. Répéter des instructions via des conditions

Toutes les structures que nous avons vu jusqu'ici permettent de tester une condition une fois, lorsqu'elle (la structure) est atteinte. Cependant, il est aussi possible d'utiliser une structure, de telle manière que ses instructions seront répétées, tant qu'une condition est vraie. Ces structures portent un nom très célèbre en programmation : les boucles. Leur contenu est exécuté jusqu'à ce que la condition de la structure est vraie.

La boucle la plus célèbre est la boucle "TANT QUE". D'un point de vue assez haut niveau, elle peut se traduire par "TANT QUE une condition est vraie, faire quelque chose". En gérant efficacement la condition qui anime la boucle, on peut dériver cette boucle en pleins d'autres types de boucles. Cette condition est nommée "condition d'exécution". Voici un petit exemple de pseudo-code, utilisant "TANT QUE", pour une multiplication :

demander nombre_a_multiplier à l'utilisateur
demander multiplicateur à l'utilisateur

mettre nombre_de_multiplication à 0
mettre resultat à 0

tant que nombre_de_multiplication plus petit que multiplicateur
--- ajouter nombre_a_multiplier à resultat
--- ajouter 1 à nombre_de_multiplication
Dans cette exemple, tant que nombre_de_multiplication est plus petit que multiplicateur, on ajoute nombre_a_multiplier à resultat. Comme on ajoute 1 à chaque passage à nombre_de_multiplication, nombre_de_multiplication est égal au nombre de fois que la boucle se répète. Au final, resultat sera égal à nombre_a_multiplier + nombre_a_multiplier + ... + nombre_a_multiplier, multiplicateur fois, soit nombre_a_multiplier * multiplicateur. D'ailleurs, une répétition de boucle est appelée une itération de boucle.

Une boucle qui peut vous venir à l'esprit est la boucle "RÉPÉTER X FOIS". Cependant, cette boucle n'est en général pas primaire en programmation, bien que cette appelation est possible en pseudo-code. Il est cependant possible de reproduire cette boucle avec "TANT QUE". Pour cela, il faut 2 variables, une qui contient le nombre d'itérations nécessaires, et une contenant le nombre d'itérations à un moment T. À chaque itérations de la boucle, la variable contenant le nombre d'itérations augmente de 1. Lors ce qu'elle sera égal au nombre d'itérations nécessaires, il y aura eu ce nombre là d'itérations, donc la condition d'exécution doit devenir fausse. Il faut donc utiliser comme condition d'exécution "nombre_itérations plus petit que nombre_itérations_nécessaires". En pseudo-code, cela donne :

mettre iterations_necessaires à 5
mettre nombre_iterations à 0

tant que nombre_iterations plus petit que iterations_necessaires
--- afficher "Ce message sera affiché 5 fois."
--- ajouter 1 à nombre_iterations
Très similaire à ce que l'on a vu dans l'exemple d'en haut.

Le problème de ce système est que, si la condition d'exécution n'est jamais fausse, la boucle ne s'arrête jamais. Dans ce cas là, la boucle est appelée une boucle infinie. Cependant, si cela n'est pas prévu, le programme se gèle, jusqu'à ce que vous l'arrêtiez. Il faut donc faire attention à la condition d'exécution. Un exemple de boucle infini, inspiré des exemples d'en haut, serait en pseudo-code :

mettre iterations_necessaires à 5
mettre nombre_iterations à 0

tant que nombre_iterations plus petit que iterations_necessaires
--- afficher "Ce message sera affiché 5 fois."
--- enlever 1 à nombre_iterations
Dans ce cas là, nombre_iterations ne dépassera jamais iterations_necessaires, et la boucle se répétera indéfiniment.

Contenu

B. Les conditions en C++

Tout ce que nous avons vu est, bien évidemment, présent en C++. Nous allons voir dés maintenant sous quelle forme.

a. Les variables "conditions"

Comme nous l'avons vu, le résultat d'une condition représente une donnée, qui est soit vraie soit fausse. Ces données sont présentes en C++, sous forme de variables, de type "bool". Ce type peut avoir deux valeurs : "true" (vrai) ou "false" (faux). En général, "false" équivaut au 0 numérique et "true" à n'importe quel autre valeur numérique. Pour créer une variable "bool", vous pouvez procéder ainsi :

// Avec "true" et "false"
bool vrai = true;
bool faux = false;

// Avec des nombres
vrai = 1;
faux = 0;

Pour faire des comparaisons, il faut utiliser le système d'opérateurs que nous avons vu au dernier cours. Ils sont appelés les opérateurs de comparaisons. L'opérateur de comparaison permettant de vérifier que deux valeurs sont égales est "==". À ne pas confondre avec "=", qui est un opérateur d'assignement (voir dernier cours). La valeur d'une comparaison de ce genre est une rvalue (voir dernier cours). Ils sont assez facilement utilisables :

// Attention à l'ordre des opérateurs
int age = 10;
bool vrai = (age == 10);
bool faux = (age == 25);
Les autres opérateurs sont aussi assez simples. L'opérateur permettant de vérifier que deux valeurs sont différentes est "!=". Pour "plus grand que", c'est ">", et pour "plus petit que", c'est "<". Pour "plus grand ou égal à", c'est ">=", et pour "plus petit ou égal à", c'est "<=". Leur utilisation précise dépend du type des valeurs comparées. Par exemple, avec des valeurs numériques, les comparaisons sont entièrement numériques. Avec du texte (std::string), "==" et "!=" vérifient si le texte est le même ou pas. Ces valeurs peuvent être tous types de valeurs : variables, valeurs en dur...

Les opérateurs de l'algèbre de Boole vus plus haut sont aussi disponibles en C++. Ils permettent de donner un résultat via deux autres valeurs de conditions. L'opérateur "ET" s'écrit "&&", "OU" s'écrit "||" et "NON" s'écrit avec un "!" avant la condition. C'est opérateurs sont des opérateurs logiques. Ils sont exécutés après les opérateurs de comparaisons dans le compiler. Un exemple peut être :

int age = 10;
std::string nationalite = "francaise";
bool citoyen_francais = (age >= 18 && nationalite == "francaise");

Comme en algorithmique, une bonne structure des conditions est nécessaire pour ne pas se perdre. Pour ça, l'utilisation de parenthèses est possible en C++. Voici un petit exemple :

int age = 10;
bool inscrit_sur_liste_electorale = false;
std::string nationalite = "francaise";
bool peut_voter = (age >= 18 && nationalite == "francaise") && inscrit_sur_liste_electorale;

bool veut_voter = true;
bool vote_obligatoire = false;
bool va_voter = peut_voter && (veut_voter || vote_obligatoire);

b. Les structures de conditions

L'utilisation de structures de conditions est très liés à l'utilisation de données "bool", vue plus tôt. La structure de condition "SI quelque chose, faire_quelque_chose" est représenté en C++ avec la syntaxe "if(quelque_chose) {faire_quelque_chose;}". "if" est un des mots réservés par le compiler en C++. Entre parenthèses, vous devez mettre une condition, ou un résultat de condition. Entre crochets, vous devez mettre ce qui va être fait si le résultat de condition est "true". Voici un petit exemple :

int age = 10;
if(age >= 18) {
    // Écrire "Majeur" dans la console
    std::cout << "Majeur" << std::endl;
}

// Cas aussi possible
bool est_majeur = (age >= 18);
if(est_majeur) {
    // Écrire "Majeur" dans la console
    std::cout << "Majeur" << std::endl;
}
À noter que, ici, l'indentation n'est pas nécessaire, au contraite du pseudo-code. Ce qui sera exécuté n'est que ce qui est entre crochets. On peut donc le présenter comme on veut, avec indentation, sauts de lignes... Pour rendre cela plus jolie.

La structure "SELON" a une syntaxe très similaire à la structure "if". Pour l'utiliser, il faut rajouter "else {chose_a_faire;}" après les crochets du "if". Si la condition de "if" est "false", les choses à faire dans les crochets de "else" sont faites. Elle reste très simple à utiliser :

int age = 10;
if(age >= 18) {
    // Écrire "Majeur" dans la console
    std::cout << "Majeur" << std::endl;
}
else {
    // Écrire "Mineur" dans la console
    std::cout << "Mineur" << std::endl;
}
Elle complète très bien "if".

Finalement, la dernière structure pour compléter "if" et "SINON SI". C'est un mélange de "if" et "else", et ça s'écrit "else if(condition){faire_quelque_chose;}". Il fonctionne exactement comme "if", à l'exception près qu'il faut rajouter "else" devant, et qu'elle n'arrive que si les précédents "if" sont faux. Ce sera plus clair avec un exemple :

int age = 0;
std::cin >> age;
if(age >= 60) {
    std::cout << "Vous êtes un boomer." << std::endl;
}
else if(age >= 44) {
    std::cout << "Vous êtes un gen X." << std::endl;
}
else if(age >= 24) {
    std::cout << "Vous êtes un gen Y." << std::endl;
}
else if(age >= 10) {
    std::cout << "Vous êtes un gen Z." << std::endl;
}
else {
    std::cout << "Vous êtes un gen Alpha." << std::endl;
}

Pour en finir avec tout cela, il reste une structure avoir : la structure "SELON". Bien qu'elle ne soit pas si utilisée que ça en C++, il est important de la connaître. En C++, elle commence avec la syntaxe "switch(variable){comparaison}". "variable" entre parenthèse est la variable à laquelle on va tester des valeurs. Cependant, la comparaison n'est qu'un "==", et ne fonctionne que avec des nombres entiers. Entre crochets, on doit utiliser une syntaxe précise pour tester une valeur. Il faut utiliser la syntaxe "case valeur: faire_quelque_chose; break;". Si la variable à la valeur mise après "case", alors tout ce qui suit après le ":" jusqu'au "break;" sera fait. Nous verrons un peu plus tard qu'est ce qu'est "break". On peut y attribuer un comportement par défaut si aucun "case" n'est juste, avec "default: faire_quelque_chose;". Pas besoin de "break;" ici. On va prendre un exemple assez nouveau :

int exercice = 2;
switch(exercice) {
    case 1 :
        std::cout << "Vous êtes à l'exercice 1." << std::endl;
    break;
    case 2 :
        std::cout << "Vous êtes à l'exercice 2." << std::endl;
    break;
    case 3 :
        std::cout << "Vous êtes à l'exercice 3." << std::endl;
    break;
    default :
        std::cout << "Vous avez fini." << std::endl;
}

c. Les boucles

En C++, l'utilisation des boucles est très similaire à l'utilisations des autres structures de données. La boucle "TANT QUE" à exactement la même syntaxe que "if", à l'exception qu'on doit mettre "while" à la place de "if". Voici un très simple cas d'utilisation :

int iterations_necessaires = 5;
int nombre_iterations = 0;
while(nombre_iterations < iterations_necessaires) {
    nombre_iterations++;
    std::cout << "Ce message sera affiché 5 fois." << std::endl;
}

Une autre boucle extrêmement similaire existe en C++. Cependant, elle n'a pas vraiment d'équivalent en pseudo-code. En effet, le problème avec la boucle "while" est que, si la condition est fausse à l'entrée de la boucle, alors elle ne s'exécutera pas une seule fois. Pour obliger la boucle à se répéter au moins une fois, il faut un peu changer sa syntaxe. Pour cela, il faut placer le "while(condition)" après les crochets, lui rajouter un ";" après, et rajouter "do" avant les crochets. Voici un cas d'utilisation similaire à celui d'en haut :

int iterations_necessaires = 0;
int nombre_iterations = 0;
do {
    nombre_iterations++;
    std::cout << "Ce message sera affiché 1 fois." << std::endl;
} while(nombre_iterations < iterations_necessaires);

Ces boucles là restent assez simples, mais il existe une boucle un peu plus complexe. De plus, comme en pseudo-code, elle n'a pas vraiment d'équivalent en pseudo-code. Il s'agit de la boucle "for", qui a pour syntaxe "for(assignement;condition;iteration)". Entre parenthèse, "l'assignement" correspond à la création / modification d'une variable avant d'entrer dans la boucle. Si aucune variable n'a besoin d'être crée ou modifiée pour pouvoir utiliser la boucle, cette endroit peut être laissé vide. La "condition" représente la condition d'exécution de la boucle, comme dans une boucle "TANT QUE". L'itération est ce qu'il va arriver à chaque itération de la boucle. Ces 3 choses sont des instructions, donc doivent finir par un ";" (même si l'instruction est vide). En général, cette boucle est très similaire à la boucle pseudo-code "RÉPÉTER X FOIS", bien qu'elle soit beaucoup plus modulable. Voici un cas d'utilisation similaire à ceux d'en haut :

// On crée une variable int "i", on défini comme condition d'exécution "i plus petit que 5", et à chaque itération de boucle, on ajoute 1 à "i"
for(int i = 0;i<5;i++) {
    std::cout << "Ce message sera affiché 5 fois." << std::endl;
}

// Pareil que en haut, bien qu'on n'ait pas d'assignement nécessaire
int i = 0;
for(;i<5;i++) {
    std::cout << "Ce message sera affiché 5 fois." << std::endl;
}
Nous pouvons faire plein d'autres choses avec cette boucle, comme l'utiliser avec des itérateurs. Cependant, pour utiliser pleinement cette boucle, il faut bien la comprendre, ce qui peut être assez complexe pour certains.

Pour en finir avec les boucles, il faut savoir qu'il est possible d'agir sur leur déroulé, pendant leur exécution. En effet, l'instruction "break;" permet de sortir de la boucle, pour de bon, qu'elle que soit la condition d'exécution. Elle peut être utilisé dans une boucle, pour simplifier la condition d'exécution de la boucle. De manière un peu moins brutale, l'instruction "continue;" permet d'ignorer tout ce qui vient après elle dans la boucle, et de directement passer à la prochaine itération. Bien que certains développeurs les détestent, il est quand même important de les connaître.

Voici la base des conditions et des boucles en C++. Cependant, il y a une dernière chose très importante à savoir. En effet, ce que je vous aie expliqué n'est, en vrai, pas vraiment la base, puis ce qu'il s'agit de l'entièreté de cette partie du C++. Le problème principal n'est, en effet, pas de connaître la syntaxe de ces boucles, mais réussir à comprendre leur puissance et comment précisement les utiliser. Pour cela, il faut de la pratique.