Aller au contenu

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 / DOWNTO
TO pour compter vers le haut, DOWNTO pour 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.