Chapitre 11 — Des boucles avec FOR
Dans les années 80, je travaillais comme programmeur dans une société qui fabriquait des machines
à peser. Un des projets que je devais faire, c'était de créer un programme qui permette de charger
des poids sur une série de balances et de lire les affichages. La station de test devait s'occuper
de quatre machines l'une après l'autre. Un collègue avait essayé de le faire mais n'avait pas réussi
parce qu'après avoir développé le code pour une machine, il avait essayé de le recopier quatre fois.
Un micro-ordinateur
BBC Model B
avait 32 Ko de mémoire : son programme n'y entrait pas. Il ignorait complètement la capacité
de l'ordinateur de lire le même code de façon répétée en se servant d'une boucle
FOR.
Effectivement, j'ai réécrit le programme, pour qu'il fasse ceci :
REM Contrôle de balances
FOR Balance%=1 TO 4
REM charger les poids
REM faire les lectures
REM afficher les résultats
NEXT Balance%
END
La ligne 2 est le commencement de la boucle. Elle dit à l'ordinateur d'utiliser une variable
(Balance% dans ce cas) pour conserver le compte du nombre de fois qu'une boucle a été exécutée
et arrêter la boucle quand elle dépasse une certaine limite, dans cet exemple : 4.
À la première rencontre de cette ligne, la variable Balance% est créée et mise à 1.
Les lignes 3 à 5 sont ensuite exécutées. Quand la ligne 6 est exécutée à son tour, le programme saute
en arrière jusqu'à la ligne 2, augmente Balance% de 1, la compare avec la valeur finale,
voit qu'elle est inférieure et exécute à nouveau les lignes 3 à 5.
À la dernière répétition, quand Balance% vaut 4, le programme augmente Balance% de 1,
voit qu'il a dépassé la valeur finale et saute à la ligne 7 où il continue avec la suite du programme.
On voit donc que la boucle est utilisée avec trois mots-clés nouveaux
• FOR
pour indiquer le début de la boucle et le nom du compteur ;
• TO
pour indiquer la limite jusqu'à laquelle le compteur de bouble doit compter ;
• NEXT
pour indiquer que le compteur de boucle est augmenté de 1.
Le programme ci-dessus a beaucoup de fonctionnalités pour 2 lignes de code, mais comme vous
l'avez probablement deviné, ça ne s'arrête pas là. Tout d'abord, la variable compteur peut être
utilisée dans la boucle elle-même pour que le code sache où il en est :
REM Contrôle de balances
FOR Balance%=1 TO 4
PRINT "Test de la balance n° : ";Balance%
REM charger les poids
REM faire les lectures
REM afficher les résultats
NEXT Balance%
END
...ou bien pour prendre des décisions :
REM Contrôle de balances
FOR Balance%=1 TO 4
CASE Balance% OF
WHEN 1 : PRINT "Test de la 1re balance"
WHEN 2 : PRINT "Test de la 2e balance"
WHEN 3 : PRINT "Test de la 3e balance"
WHEN 4 : PRINT "Test de la 4e balance"
ENDCASE
REM charger les poids
REM faire les lectures
REM afficher les résultats
NEXT Balance%
END
...ou encore toute autre chose pour laquelle vous pourriez en avoir besoin. Évidemment,
le compteur n'a aucune validité en dehors de la boucle, aussi ne l'y utilisez pas.
Les valeurs de début et de fin peuvent prendre n'importe quelle valeur logique :
FOR Compteur%=-10 TO 10
PRINT Compteur%
NEXT Compteur%
ou bien, les valeurs de début et de fin peuvent être des variables ou des expressions :
FOR Compteur%=ValeurMin% TO ValeurMax%-10
PRINT Compteur%
NEXT Compteur%
Chaque compteur commencera à la première valeur et augmentera
de un jusqu'à ce qu'il dépasse la deuxième valeur. Vous, en tant que programmeur, devez être prudent
ici. Si la valeur de fin est inférieure à la valeur de départ,
« BB4W »
ne se plaindra pas mais sans doute serez-vous intrigué sans comprendre pourquoi votre boucle
ne se déroule pas. Diverses autres formes de
BASIC réagiront
de façon différente dans cette situation.
BBC BASIC
fera tourner la boucle au moins une fois, quelles que soient les valeurs que vous lui attribuerez.
Il se peut que parfois vous souhaitiez que le programme répète des boucles avec
des incréments (des intervalles) différents de un. Là, un nouveau mot-clé peut être utilisé pour forcer
cette situation. Le code suivant affichera tous les nombres impairs jusqu'à 20.
REM STEP démonstration
FOR Compteur%=1 TO 20 STEP 2
PRINT Compteur%
NEXT Compteur%
END
Le mot-clé
STEP
force l'incrémentation à la valeur spécifiée. Là encore, l'incrément peut être n'importe quelle valeur
logique ou n'importe quelle expression pour le type de variable que vous utilisez.
FOR I=1 TO 5 STEP 0.5
REM ...
Il peut aussi être négatif :
FOR I%=10 TO 1 STEP -1
REM ...
Dans ce cas, le
BASIC calcule
qu'il recule et au lieu de s'arrêter quand I% est plus grand que 1 – ce qui se
passerait instantanément – il s'arrête quand I% est inférieur à 1 :
vraiment, c'est du bon sens.
Comme pour tout autre construction, on peut faire des imbrications
de boucles l'une dans l'autre :
FOR I%=1 TO 5
FOR J%=1 TO 5
PRINT I%,J%
NEXT J%
NEXT I%
Ici, la boucle intérieure est exécutée 5 fois pour chaque exécution de la boucle extérieure.
La boucle intérieure doit être intégralement contenue dans la boucle extérieure. Essayez d'échanger
NEXT J% et NEXT I% et vous verrez que vous produirez une erreur.
Après toutes ces variations sur
FOR,
l'autre bout de la boucle n'est pas très passionnant.
NEXT
est utilisé pour marquer l'emplacement de la fin de la boucle. Le nom de la variable compteur n'y est pas
véritablement indispensable parce que le
BASIC
est assez intelligent pour calculer quel
NEXT
correspond à quel
FOR.
Je préfère les indiquer, parce que cela rend le code plus facile à lire, surtout si la boucle
couvre plus de lignes que l'écran ne peut en afficher en une seule fois.
Dans notre exemple imbriqué précédent, on aurait pu remplacer la ligne 4 par :
NEXT J%,I%
Essayez-le : enlevez d'abord la ligne 5 ou faites-la précéder de
REM.
Le programme tournera comme précédemment en exécutant 5 boucles intérieures pour chaque boucle
extérieure. Le
BASIC
acceptera même :
NEXT ,
Personnellement, je n'aime pas particulièrement cette méthode parce qu'il n'est pas évident
de voir où finissent les boucles et cela cause du tort au décalage horizontal que l'éditeur fournit
de façon si claire. Ce n'est qu'une préférence personnelle pourtant, et vous trouverez ceci
dans d'autres codes.
Un truc : Précautions avec les boucles FOR
|
Pour finir, je souhaiterais mentionner plusieurs erreurs courantes que l'expérience a révélées :
a)
Ne quittez pas une boucle en utilisant
GOTO ;
en cas de nécessité, forcez le compteur à une valeur supérieure à la valeur finale et laissez
le processus se terminer naturellement.
b)
Nous vous supplions à genoux : s'il vous plaît ! n'utilisez pas de
NEXT
conditionnels. Beaucoup condamnent les
GOTO
parce qu'ils font prendre de mauvaises habitudes de programmation, mais il est possible de faire
de mauvaises choses avec n'importe quelle commande. Ce dont je veux parler,
c'est ce genre de choses :
REM Programme ...
FOR I%=1 TO NombreMax
PRINT I%^2
IF I% MOD J%=0 THEN NEXT
IF I%-1=J% NEXT ELSE J%=I%+1 : NEXT
REM Reste du programme ...
Il y a tellement de
NEXT
là-dedans que l'éditeur n'y comprend plus rien, et vous non plus. Ne mettez jamais qu'un seul
NEXT
pour chaque
FOR
et donnez-lui une ligne à lui seul pour que le décalage horizontal vous permette de voir clairement
où commence et où finit la boucle. On peut toujours utiliser des blocs de
IF
pour exécuter du code de façon conditionnelle, si cela est nécessaire.
c)
Il est courant, chez les programmeurs de nombreux langages, d'utiliser I% et J%
comme compteurs. C'est tellement vrai qu'il est facile d'oublier un compteur et de le réutiliser
au milieu du code d'une autre boucle :
FOR I%=1 TO 10
REM ... plusieurs pages de code ...
FOR J%=1 TO 10
FOR I%=1 TO 99
REM Problème ici à se servir de I%
REM à nouveau parce que nous venons de
REM réinitialiser la première boucle
REM Reste du programme ...
Vous verrez ce que je veux dire un jour, parce que tout le monde fait cette erreur,
même après avoir été prévenu !
|
Exercices
11.1
Écrivez un programme avec une boucle
FOR
pour afficher la table de multiplication par 5. Chaque ligne doit avoir ce format :
1 * 5 = 5
2 * 5 = 10
...
12 * 5 = 60
11.2
Utilisez deux boucles
FOR
imbriquées pour dessiner un rectangle sur l'écran en vous servant d'une ligne comme
PRINT TAB(X,Y);"*"
Fin du Chapitre 11
|