La programmation n'aurait que très peu d'intéret si elle ne permettait pas aux ordinateurs de réagir différemment selon différentes conditions.
Une machine programmable doit pouvoir effectuer des traitements différents selon les données qu'elle doit traiter.
Cela est possible grace à l'existence des structures de controles dans les langages de programmation : la conditionnelle et les boucles.
L'objet de cette partie du cours est d'expliquer le fonctionnement d'une conditionnelle.
La conditionnelle If existe en deux variantes: Le If ... Then et If ... Then ... Else.
La structure de contrôle If ... Then s'écrit de la manière suivante:
If condition Then Begin Instructions à exécuter si la condition est vraie End;
La condition n'est rien d'autre qu'une expression logique.
Les instructions entre begin et end ne seront exécutées que si la condition est vraie.
S'il n'y a qu'une seule instruction à exécuter, on peut ommettre les mots clé begin et end :
If condition Then Instruction à exécuter ;
Prenons un exemple :
If n > 0 Then n := n - 1 ;
Si par exemple n vaut 5 juste avant l'exécution du If ... Then, la condition n > 0 est vérifiée. L'ordinateur va donc exécuter l'affectation n := n - 1. n vaudra donc 4 à la sortie de la conditionnelle.
Si n vaut -1 par contre, la condition n > 0 n'est pas vérifiée. L'affectation ne sera pas exécutée et n vaudra toujours -1 à la sortie de la conditionnelle.
Le If ... Then ... Else est une autre forme de conditionnelle.
Elle permet d'exécuter certaines instructions si une condition est vraie et d'autres, si elle est fausse.
Voilà sa syntaxe:
If condition Then begin Instructions à exécuter si la condition est vraie End Else begin Instructions à exécuter si la condition est fausse End;
De même, les begin et end ne sont sont pas nécessaires s'il n'y a qu'une seule instruction.
Prenons un exemple :
If n > 0 Then n := n - 1 Else n := n + 1;
Remarquez que nous n'avons pas mis de point-virgule après la première effectation. Si nous l'avions fait, le compilateur aurait généré une erreur de syntaxe, car il aurait interprété ceci comme un if ... then simple suivi du mot clé else qui n'aurait rien à voir ici dans ce cas.
Par contre, le point-virgule est nécessaire après la deuxième affectation pour marquer la fin de la conditionnelle.
Que se passe-t-il lors de l'exécution de cette conditionnelle ?
Supposons par exemple que n vale 5 juste avant l'exécution du If ... Then ... Else. La condition n > 0 est vérifiée. L'ordinateur va donc exécuter l'affectation n := n - 1. Par contre, l'affectation n := n + 1 ne sera pas exécutée. n vaudra donc 4 à la sortie de la conditionnelle.
Si n vaut -1 par contre, la condition n > 0 n'est pas vérifiée. L'affectation n := n - 1 n'est donc pas exécutée. Mais comme la condition est fausse, l'affectation n := n + 1 sera exécutée. n vaudra donc 0 à la sortie de la conditionnelle.
Les instructions à l'intérieur d'un If ne sont pas forcément des affectations comme dans les exemples précédents.
On peut également y mettre d'autres structures de controle et en particulier d'autres Ifs.
Exemple :
If n > 0 Then n := n - 1 Else If n >= -3 Then n := n + 1 Else n := 2 * n;
Pour n=5 l'instruction exécutée est n := n - 1. n vaudra donc 4 à la sortie de la conditionnelle.
Pour n=-1 l'instruction exécutée est n := n + 1. n vaudra donc 0 à la sortie de la conditionnelle.
Pour n=-4 l'instruction exécutée est n := 2 * n. n vaudra donc -8 à la sortie de la conditionnelle.
Dans l'exemple précédent on a deux niveaux d'imbriquation. Mais on peut avoir autant de niveaux d'imbriquation qu'on le souhaite.
L'imbrication de ifs peut conduire à des programmes plus rapides (voir exercice Min-Max-Med), mais elle peut également compliquer l'écriture du code, notamment dans la protection d'un programme contre les erreurs.
Prenons par exemple un programme utilisant une date définie par un jour (nombre entier entre 1 et 31), un mois (nombre entier entre 1 et 12) et une année de ce siècle (nombre entier supérieur à 2000). Ces trois données sont lues depuis trois zones de texte (respectivement ZT_Jour, ZT_Mois et ZT_Annee) dans des variables entières, respectivement Jour, Mois, Annee. Ce traitement est effectué par la procédure évènementielle associée au bouton BT_GererDate.
Pour tester la validité de ces données avec des if imbriqués, on écrirait le code suivant:
procedure TForm1.BT_GererDateClick(Sender: TObject) var Jour,Mois,Annee: integer; begin LireEntier (Jour, ZT_Jour); If ( Jour < 1) or (Jour > 31) Then ShowMessage ('Numero du jour non valide!') Else begin LireEntier (Mois, ZT_Mois); If (Mois < 1) or (Mois > 12) Then ShowMessage('Numero du mois non valide!') Else Begin LireEntier(Annee,ZT_Annee); If Annee < 2000 Then ShowMessage ('Année non valide!') Else Begin Traitement de la date End End End End;
Pour raccourcir ce genre d'écriture, on peut utiliser l'instruction Exit, qui permet de forcer la fin de l'exécution du sous-programme qui la contient. Avec cette instruction, l'exemple précédent peut être écrit sans aucune imbrication de ifs:
procedure TForm1.BT_GererDateClick(Sender: TObject) var Jour,Mois,Annee: integer; begin LireEntier (Jour, ZT_Jour); If ( Jour < 1) or (Jour > 31) Then Begin ShowMessage ('Numero du jour non valide!'); Exit End; LireEntier (Mois, ZT_Mois); If (Mois < 1) or (Mois > 12) Then Begin ShowMessage('Numero du mois non valide!'); Exit End; LireEntier(Annee,ZT_Annee); If Annee < 2000 Then Begin ShowMessage ('Année non valide!'); Exit End; Traitement de la date End;
La conditionnelle Case est utilisée lorsque l'on veut effectuer différents traitements selon la valeur d'une expression quelconque.
Voilà sa syntaxe:
Case Expression Of V1 : Instructions à exécuter lorsque l'expression vaut V1 ; V2 : Instructions à exécuter lorsque l'expression vaut V2 ; . . VN : Instructions à exécuter lorsque l'expression vaut VN ; Else Instructions à exécuter dans les autres cas ; End;
La partie Else est optionnelle.
Voici, par exemple comment déterminer le nom d'un mois en fonction de son numéro avec une instruction Case:
Case NumeroMois Of 1 : NomMois :='Janvier'; 2 : NomMois :='Fevrier'; . . 12 : NomMois :='Decembre'; Else ShowMessage ('Numero de mois inexistant!') End;