Logo

Marco Cantù
L'essentiel sur Pascal

Traduit de l'anglais par Iannis Papageorgiadis ipapag@village.uunet.be

Chapitre 5

Les instructions

Si les types de données constituent une des bases de la programmation Pascal, les instructions en constituent l'autre. Les instructions du langage de programmation sont basées sur des mots réservés et sur d'autres éléments qui permettent d'indiquer à un programme une séquence d'opérations à effectuer. Les instructions se trouvent souvent dans des procédures ou dans des fonctions, comme nous le verrons au chapitre suivant. Nous nous arrêterons maintenant aux types fondamentaux de commandes qu'on peut utiliser pour créer un programme.

Instruction simple et instruction composée

Une instruction Pascal est simple lorsqu'elle ne contient aucune autre instruction. Les assignations et les appels de procédure sont des exemples d'instructions simples :
X := Y + Z;  //  assignation
Randomize;   //  appel de procédure
Habituellement, les instructions font partie d'une instruction composée, délimitée par les mots réservés begin et end. Une instruction composée peut apparaître à la place d'une instruction Pascal générique. Voici un exemple :
begin
  A := B;
  C := A * 2;
end;
Le point-virgule qui suit la dernière instruction n'est pas obligatoire, comme on le voit ci-dessous :
begin
  A := B;
  C := A * 2
end;
Les deux versions sont correctes. La première comporte un point-virgule inutile (mais inoffensif). Ce point-virgule constitue en fait une instruction vide, c'est-à-dire une instruction sans code. Remarquez que, parfois, les instructions vides peuvent être utilisées dans les boucles ou dans d'autres cas particuliers.
 
Remarque : Bien que ces points-virgule terminaux ne servent à rien, nous avons tendance à les utiliser et nous vous suggérons d'en faire autant. Après avoir écrit quelques lignes, vous pourriez vouloir ajouter une ou plus instructions. Si le dernier point-virgule est manquant, il faut penser à l'ajouter; le mieux serait qu'il soit ajouté dès le début.

Les instructions d'assignation

Les assignations (N.D.T. : on dit aussi affectations) en Pascal utilisent l'opérateur "deux points-égal" (: =), une notation bizarre pour les programmeurs habitués à d'autres langages. L'opérateur =, qui est utilisé pour les affectations dans d'autres langages, sert en Pascal, pour effectuer le test d'égalité.
 
Remarque : En utilisant des symboles différents pour une assignation et pour un test d'égalité, le compilateur Pascal (comme le compilateur C) peut traduire plus rapidement le code source, parce qu'il ne doit pas examiner le contexte dans lequel est utilisé l'opérateur pour déterminer sa signification. L'utilisation d'opérateurs différents rend également le code plus facile à lire.

Les instructions conditionnelles

Une instruction conditionnelle est utilisée soit pour exécuter une des instructions qui la composent soit pour n'en exécuter aucune, en fonction d'un test. Il existe deux sortes d'instructions conditionnelles : les instructions if et les instructions case.

Les instructions If

L'instruction if peut être utilisée pour exécuter une instruction si une certaine condition est remplie (if-then), ou pour choisir entre les deux termes d'une alternative (if-then-else). La condition est constituée par une expression booléenne. Un exemple simple en Delphi vous montrera comment écrire des instructions conditionnelles. Pour commencer, créez une nouvelle application, et placez sur la fiche deux cases à cocher (CheckBox) et quatre boutons. Ne changez pas les noms des boutons ni ceux des cases à cocher, mais double cliquez sur chaque bouton pour ajouter un gestionnaire pour leur événement OnClick. Voici une instruction if simple pour le premier bouton:
procedure TForm1.Button1Click(Sender: TObject);
begin
  // Instruction if simple
  if CheckBox1.Checked then
    ShowMessage ('la case à cocher 1 est cochée')
end;
Lorsque vous cliquez sur le bouton, si la première case à cocher est cochée, le programme vous affichera un message simple (fig.5.1). Nous avons utilisé la fonction ShowMessage parce que c'est la plus simple des fonctions Delphi que vous pouvez utiliser pour afficher un court message à l'intention de l'utilisateur.

Figure 5.1: Le message affiché par l'exemple IfTest lorsque vous pressez le premier bouton et que la première case à cocher est cochée.

Si vous cliquez le bouton et que rien ne se passe, cela veut dire que la case à cocher n'était pas cochée. Dans un tel cas, il aurait probablement mieux valu rendre la chose plus explicite, comme avec le code du deuxième bouton qui utilise une instruction if-then-else :

procedure TForm1.Button2Click(Sender: TObject);
begin
  // instruction if-then-else
  if CheckBox2.Checked then
    ShowMessage ('la case à cocher 2 est cochée')
  else
    ShowMessage ('la case à cocher 2 n''est pas cochée');
end;
Notez qu'on ne peut pas avoir un point-virgule à la fin de la première instruction et avant le mot réservé else, sinon le compilateur détectera une erreur de syntaxe. En fait, l'instruction if-then-else constitue une instruction simple, si bien que vous ne pouvez pas placer un point-virgule en son milieu.

Une instruction if peut être très complexe. La condition peut se transformer en une série de conditions (avec les opérateurs booléens and, or, not); ou l'instruction if peut aussi contenir une seconde instruction if. Les deux derniers boutons de l'exemple IfTest illustrent ces cas:

procedure TForm1.Button3Click(Sender: TObject);
begin
  //  Instruction avec condition double
  if CheckBox1.Checked and CheckBox2.Checked then
    ShowMessage ('Les deux cases à cocher sont cochées')
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  //  instruction if composée
  if CheckBox1.Checked then
    if CheckBox2.Checked then
      ShowMessage ('Les cases à cocher 1 et 2 sont cochées')
    else
      ShowMessage ('Seule la case à cocher 1 est cochée')
  else
    ShowMessage (
      'la case à cocher 1 n''est pas cochée, aucune importance pour la 2')
end;
Regardez attentivement le code et exécutez le programme pour voir si vous comprenez tout. Si vous avez des doutes concernant la construction du programme, le fait d'écrire un programme très simple comme celui-ci peut vous aider beaucoup. Vous pouvez ajouter d'autres cases à cocher et augmenter la complexité de ce petit exemple, en effectuant les tests que vous souhaitez.

Les instructions case

Si vos instructions if deviennent très complexes, vous pouvez les remplacer par des instructions case. Une instruction case consiste en une expression (N.D.T. : le sélecteur) utilisée pour sélectionner une valeur, une liste des valeurs possibles, ou un intervalle de valeurs. Ces valeurs sont des constantes (N.D.T. : les constantes de cas), elles doivent être uniques et d'un type scalaire. Éventuellement, il peut y avoir une instruction else qui sera exécutée si aucune constante de cas ne correspond à la valeur du sélecteur. Voici deux exemples simples:
case Number of
  1: Text := 'Un';
  2: Text := 'Deux';
  3: Text := 'Trois';
end;
case MyChar of
  '+' : Text := 'Signe plus';
  '-' : Text := 'Signe moins';
  '*', '/': Text := 'Multiplication ou division';
  '0'..'9': Text := 'Nombre';
  'a'..'z': Text := 'Caractère minuscule');
  'A'..'Z': Text := 'Caractère majuscule';
else
  Text := 'Caractère inconnu';
end;

Les boucles en Pascal

Le langage Pascal possède les instructions de répétition typiques de la plupart des langages de programmation, y compris les instructions for, while et repeat. Plusieurs d'entre elles vous sont familières si vous avez utilisé d'autres langages de programmation, de sorte que nous les traiterons brièvement.

La boucle for

En Pascal, la boucle for est basée strictement sur un compteur qui peut soit croître soit décroître chaque fois que la boucle est exécutée. Voici un exemple simple d'une boucle for utilisée pour additionner les dix premiers nombres :
var
  K: Integer;
begin
  K := 0;
  for I := 1 to 10 do
    K := K + I;
La même instruction for pourrait être écrite en utilisant un compteur qui décroît:
begin
  K := 0;
  for I := 10 downto 1 do
    K := K + I;
En Pascal, la boucle for est moins souple que dans d'autres langages (il n'est pas possible de spécifier un incrément différent de un), mais elle est simple et facile à comprendre. Si vous souhaitez tester une condition plus complexe, ou utiliser un compteur personnalisé, vous devez utiliser une des instructions while ou repeat à la place de for.
 
Remarque : Le compteur d'une boucle for ne doit pas être nécessairement un nombre. N'importe quelle valeur de type scalaire, comme un caractère ou un type énuméré, peut être utilisée.

Les instructions while et repeat

La différence entre les boucles while-do et repeat-until réside dans le fait que le code de l'instruction repeat est toujours exécuté au moins une fois. Vous comprendrez facilement pourquoi en observant un exemple simple:
while (I <= 100) and (J <= 100) do
begin
 // on utilise I et J pour effectuer un calcul...
  I := I + 1;
  J := J + 1;
end;

repeat
  // on utilise I et J pour effectuer un calcul...
  I := I + 1;
  J := J + 1;
until (I > 100) or (J > 100);
Si la valeur initiale de I ou de J est supérieure à 100, les instructions situées à l'intérieur de la boucle repeat-until sont, de toute façon, exécutées une fois.
 
L'autre différence fondamentale entre ces deux instructions est que la boucle repeat-until a une condition inversée. La boucle est exécutée jusqu'à ce que la condition soit vraie. Quand la condition devient vraie, la boucle se termine. C'est le contraire de la boucle while-do qui est, elle, exécutée tant que la condition est vraie. C'est pour cette raison que nous avons dû inverser la condition dans le code ci-dessus afin d'obtenir une instruction similaire.

Un exemple de boucles

Pour explorer les détails des boucles, voyons un petit exemple Delphi. Le programme Loops met en évidence la différence entre une boucle avec un compteur fixe et une boucle avec un compteur presque aléatoire. Commencez avec un nouveau projet, placez sur la fiche principale une boîte liste (ListBox) et deux boutons et donnez aux boutons un nom approprié (BtnFor et BtnWhile) en modifiant leur propriété Name dans l'inspecteur d'objets. Vous pouvez également supprimer les lettres Btn de la propriété Caption (et même lui ajouter éventuellement le caractère & pour activer la lettre suivante en tant que raccourci clavier). Voici un résumé de la description textuelle de cette fiche:
object Form1: TForm1

  Caption = 'Loops'

  object ListBox1: TListBox ...

  object BtnFor: TButton

    Caption = '&For'

    OnClick = BtnForClick

  end

  object BtnWhile: TButton

    Caption = '&While'

    OnClick = BtnWhileClick

  end

end
Figure 5.2: A chaque pression sur le bouton For de l'exemple Loops, la boîte liste est remplie par le nombre suivant.

Maintenant nous pouvons ajouter un peu de code à l'événement OnClick des deux boutons. Le premier bouton utilise une simple boucle for pour afficher une série de nombres, comme on peut le voir à la figure 5.2. Avant l'exécution de cette boucle, qui ajoute une série de chaînes à la propriété Items de la boîte liste (ListBox), il faut nettoyer le contenu de cette même boîte liste.

procedure TForm1.BtnForClick(Sender: TObject);
var

  I: Integer;
begin
  ListBox1.Items.Clear;
  for I := 1 to 20 do
    Listbox1.Items.Add ('Chaîne ' + IntToStr (I));
end;
Le code associé au second bouton est un peu plus complexe. Dans ce cas, on utilise une boucle while basée sur un compteur qui est incrémenté aléatoirement. Pour réaliser ceci, nous avons utilisé la procédure Randomize, qui re-initialise le générateur de nombres aléatoires, et la fonction Random avec une plage de 100. Cette fonction retourne un nombre entre 0 et 99, choisi aléatoirement. Les séries des nombres aléatoires contrôlent le nombre de fois que la boucle est exécutée.
procedure TForm1.BtnWhileClick(Sender: TObject);
var
  I: Integer;
begin
  ListBox1.Items.Clear;
  Randomize;
  I := 0;
  while I < 1000 do
  begin
    I := I + Random (100);
    Listbox1.Items.Add ('Nombre aléatoire: ' + IntToStr (I));
  end;
end;
A chaque pression sur le bouton While, les nombres sont différents, puisqu'ils dépendent du générateur de nombres aléatoires. La figure 5.3 montre les résultats de deux clicks différents. Remarquez que non seulement les nombres générés sont chaque fois différents, mais que le nombre d'éléments est aussi différent. C'est-à-dire que cette boucle While est exécutée un nombre aléatoire de fois. Si vous pressez le bouton While plusieurs fois de suite, vous verrez que la boîte liste (ListBox) possède, à chaque fois, un nombre différent de lignes.

Figure 5.3: Le contenu de la boîte liste de l'exemple Loops change à chaque pression sur le bouton While. Puisque le compteur de boucle est incrémenté de façon aléatoire, à chaque action sur le bouton, la boucle doit s'exécuter un nombre différent de fois.

 

Remarque : On peut modifier le fonctionnement standard de l'exécution d'une boucle en utilisant les procédures système Break et Continue. La première interrompt la boucle; la seconde est utilisée pour passer directement au test de boucle ou à l'incrémentation du compteur, en continuant avec l'itération suivante de la boucle (à moins que la condition soit zéro ou que le compteur ait atteint sa valeur maximum). Deux procédures système supplémentaires, Exit et Halt, permettent de sortir immédiatement de la fonction ou de la procédure courante ou de terminer le programme.

L'instruction with

La dernière sorte d'instruction Pascal que nous examinerons est l'instruction with, spécifique à ce langage de programmation (elle a récemment été introduite aussi en Visual Basic), et très utile dans la programmation Delphi.

L'instruction with est tout simplement un raccourci. Lorsqu'on doit faire référence à une variable de type enregistrement (ou à un objet), au lieu de répéter chaque fois son nom, on peut utiliser une instruction with. Par exemple, lors de la présentation du type enregistrement nous avions écrit ce code :

type

  Date = record

    Year: Integer;

    Month: Byte;

    Day: Byte;

  end;



var

  BirthDay: Date;



begin

  BirthDay.Year := 1997;

  BirthDay.Month := 2;

  BirthDay.Day := 14;
En utilisant une instruction with, nous pouvons améliorer la partie finale de ce code, comme ci-dessous:
begin

  with BirthDay do

  begin

    Year := 1995;

    Month := 2;

    Day := 14;

  end;
Cette approche peut être utilisée dans les programmes Delphi pour faire référence aux composants et autres types class. Par exemple, nous pouvons ré-écrire la partie finale du dernier exemple, Loops, en utilisant une instruction with pour accéder aux éléments de la boîte liste (ListBox) :
procedure TForm1.WhileButtonClick(Sender: TObject);
var
  I: Integer;
begin
  with ListBox1.Items do
  begin
    Clear; // raccourci
    Randomize;
    I := 0;
    while I < 1000 do
    begin
      I := I + Random (100);
      // raccourci:
      Add ('Nombre aléatoire: ' + IntToStr (I));
    end;
  end;
end;
Lorsque vous travaillez avec des composants ou avec des classes en général, l'instruction with vous permet de sauter un peu de code, particulièrement dans les champs imbriqués. Par exemple, supposons que l'on doive changer l'épaisseur et la couleur du crayon d'une fiche. On peut écrire le code suivant :
Form1.Canvas.Pen.Width := 2;
Form1.Canvas.Pen.Color := clRed;
Mais il est certainement plus facile d'écrire celui-ci:
with Form1.Canvas.Pen do
begin
  Width := 2;
  Color := clRed;
end;
Lorsque vous êtes en train d'écrire du code compliqué, l'instruction with peut être efficace et vous épargner la déclaration de quelques variables temporaires, mais cela comporte un inconvénient. Cela peut rendre le code moins lisible, particulièrement quand vous travaillez avec des objets différents qui ont des propriétés similaires ou semblables.

Un inconvénient supplémentaire est que l'instruction with peut entraîner de légères erreurs de logique que le compilateur ne détectera pas. Par exemple  :

with Button1 do
begin
  Width := 200;
  Caption := 'Nouveau titre';
  Color := clRed;
end;
Ce code modifie les propriétés Caption et Width du bouton, mais il affecte la propriété Color de la fiche, et non pas celle du bouton! La raison en est que les composants TButton n'ont pas de propriété Color, et puisque ce code est exécuté depuis un objet fiche (nous sommes en train d'écrire une méthode de la fiche) on accède a cet objet par défaut. Si par contre nous avions écrit :
Button1.Width := 200;
Button1.Caption := 'Nouveau titre';
Button1.Color := clRed; // erreur!
le compilateur aurait décelé une erreur. De façon générale, on peut dire que puisque l'instruction with introduit de nouveaux identificateurs dans la portée courante, on pourrait cacher des identificateurs existants, ou accéder par erreur à un autre identificateur de la même portée (comme dans la première version de ce fragment de code). Même en tenant compte de ce type d'inconvénient, nous vous suggérons d'utiliser les instructions with parce qu'elles peuvent être réellement très pratiques et rendent même parfois le code plus lisible.

Mieux vaut cependant éviter d'utiliser des instructions with multiples, comme :

with ListBox1, Button1 do...
Le code qui suivrait serait probablement très difficile à lire, parce que pour chaque propriété définie dans ce bloc vous devriez réfléchir pour savoir à quel composant il se réfère, en fonction des propriétés respectives et de l'ordre des composants dans l'instruction with.
 
Remarque : A propos de lisibilité, Pascal ne possède pas les instructions endif ou endcase. Si une instruction if comporte un bloc begin-end, alors le end du bloc indique la fin de l'instruction. L'instruction case par contre, se termine toujours par un  end. Toutes ces instructions end, souvent rencontrées l'une après l'autre, peuvent rendre le code difficile à suivre. C'est uniquement en suivant les indentations que vous pouvez voir à quelle instruction se rapporte un end particulier. Habituellement, on résout ce problème et on rend le code plus lisible en ajoutant un commentaire après l'instruction end et en indiquant son rôle, comme dans :
if ... then
 ...
end; // if

Conclusion

Ce chapitre a exposé comment encoder des instructions conditionnelles et des boucles. Au lieu d'écrire de longues listes de telles instructions, les programmes sont habituellement décomposés en routines, procédures ou fonctions. C'est le sujet du chapitre suivant qui introduit également quelques éléments avancés du Pascal.

Prochain chapitre: Procédures et fonctions
 
© Copyright Marco Cantù, Wintech Italia Srl 1995-99