I - 3. Utiliser des conditions
A. Conditionner son programme
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 :
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" :
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" :
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" :
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 :
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 :
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 :
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 :
B. Les conditions en C++
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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 :
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.