Instruction RPG full free · IBM i (AS/400) · Structures de contrôle
FOR
Répéter avec un compteur
Répète un bloc en faisant varier un compteur d'une valeur de départ jusqu'à une limite, avec un pas croissant ou décroissant.
Syntaxe
FOR indice = début TO fin;
FOR indice = début TO fin BY pas;
FOR indice = début DOWNTO fin;
instructions;
ENDFOR;
indice- Zone numérique (entier de préférence) qui sert de compteur. Elle est initialisée avec la valeur de début.
début, fin- Valeurs ou expressions numériques de départ et de limite. La limite est comprise dans la boucle.
BY pas- Incrément à chaque tour (1 par défaut). Facultatif.
TO / DOWNTOTOpour compter vers le haut,DOWNTOpour compter vers le bas.ENDFOR- Ferme la boucle.
- Effet
- Aucun indicateur n'est positionné. À la sortie normale, le compteur vaut la première valeur qui dépasse la limite (4 après un
FOR i = 1 TO 3).
À quoi ça sert
Quand le nombre de tours est connu à l'avance (échéances, éléments d'un tableau, lignes d'une page), FOR regroupe sur une ligne l'initialisation, le test et l'incrément que l'on écrivait en colonnes avec DO et ses facteurs 1, 2 et résultat.
Pour parcourir tous les éléments d'un tableau, FOR-EACH est encore plus direct.
Exemple 1 : Compter vers le haut et vers le bas
**free
// FOR : compteur croissant, pas de 2, puis decroissant avec DOWNTO.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s i int(5);
dcl-s echeance packed(9:2) inz(1200);
dcl-s part packed(9:2);
part = echeance / 4;
for i = 1 to 4;
snd-msg 'Echeance ' + %char(i) + ' : ' + %char(part);
endfor;
for i = 1 to 9 by 2;
snd-msg 'Impair : ' + %char(i);
endfor;
for i = 3 downto 1;
snd-msg 'Compte a rebours : ' + %char(i);
endfor;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Echeance 1 : 300.00
Echeance 2 : 300.00
Echeance 3 : 300.00
Echeance 4 : 300.00
Impair : 1
Impair : 3
Impair : 5
Impair : 7
Impair : 9
Compte a rebours : 3
Compte a rebours : 2
Compte a rebours : 1
Un prêt de 1 200 en 4 échéances de 300, puis les impairs de 1 à 9 avec by 2, puis un compte à rebours avec downto.
Exemple 2 : Compteur final et limite relue
**free
// FOR : valeur du compteur apres la boucle, et limite relue a chaque tour.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s i int(5);
dcl-s limite int(5) inz(3);
dcl-s tours int(5) inz(0);
for i = 1 to 3;
tours += 1;
endfor;
snd-msg 'Apres FOR 1 a 3 : i = ' + %char(i) + ', ' + %char(tours) + ' tours';
// On modifie la limite dans la boucle : elle est relue a chaque tour.
tours = 0;
for i = 1 to limite;
tours += 1;
limite = 10;
endfor;
snd-msg 'Limite changee en cours : ' + %char(tours) + ' tours, limite = ' + %char(limite);
// Un pas trop grand : la boucle s'arrete des que la limite est depassee.
for i = 1 to 10 by 4;
tours += 1;
endfor;
snd-msg 'FOR 1 a 10 par 4 : i = ' + %char(i);
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Apres FOR 1 a 3 : i = 4, 3 tours
Limite changee en cours : 10 tours, limite = 10
FOR 1 a 10 par 4 : i = 13
Après for i = 1 to 3, i vaut 4. En modifiant limite dans la boucle, on fait 10 tours au lieu de 3 : la limite est donc relue à chaque tour. Avec by 4, la boucle s'arrête avec i = 13.
Le piège
Le compteur dépasse la limite à la sortie, et la limite est relue à chaque tour. Après FOR i = 1 TO 3, i vaut 4, pas 3 : ne réutilisez pas l'indice après la boucle comme « dernier élément traité ». Et si le corps modifie la zone qui sert de limite, la boucle en tient compte : avec limite passée à 10 dans le corps, on a fait 10 tours au lieu de 3 (deuxième exemple). Copiez la limite dans une zone de travail si elle ne doit pas bouger.