Instruction RPG full free · IBM i (AS/400) · Mots-clés de déclaration
DIM
Déclarer un tableau
Donne à une zone ou à une sous-zone un nombre fixe d'éléments, ou une taille qui s'ajuste avec DIM(*AUTO) et DIM(*VAR).
Syntaxe
dcl-s zone type dim(nombre);
dcl-s zone type dim(nombre) ctdata;
dcl-s zone type dim(*auto : maximum);
dcl-s zone type dim(*var : maximum);
nombre- Nombre d'éléments du tableau, en entier. Les éléments se lisent avec un indice entre parenthèses, de 1 à ce nombre.
*AUTO : maximum- Tableau dont le nombre d'éléments suit le plus grand indice utilisé. Il part de zéro élément et ne peut pas dépasser le maximum donné.
*VAR : maximum- Tableau de taille variable que vous ajustez vous-même en affectant
%ELEM. Il part de zéro élément ; tout indice au-delà de la taille courante est refusé. CTDATA- Les valeurs initiales viennent des lignes placées en fin de source après
**ctdata nom, une ligne par élément. - Effet
- Aucun indicateur n'est touché.
%ELEM(tableau)renvoie le nombre d'éléments (la taille courante pour *AUTO et *VAR). Un indice hors limites déclenche l'erreur d'exécution RNQ0121.
À quoi ça sert
Un tableau regroupe des valeurs de même type sous un seul nom : les montants d'une facture, les villes d'une liste de livraison, les codes d'une table de contrôle. On le parcourt avec une boucle for et on le manipule avec %LOOKUP, SORTA, %ELEM.
En RPG III, c'était un tableau défini en spécification E. Le mot-clé DIM le remplace, sur une zone isolée, une sous-zone de structure ou une structure entière.
DIM(*AUTO : max) évite de tenir un compteur à la main : on ajoute, la taille suit. DIM(*VAR : max) laisse au contraire la main au programmeur.
Exemple 1 : Tableau fixe : parcours, recherche, tri, CTDATA
**free
// DIM : tableau de montants, parcours, recherche et tri.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s montants packed(9:2) dim(5);
dcl-s villes varchar(15) dim(3) ctdata;
dcl-s i int(10);
dcl-s total packed(11:2);
dcl-s pos int(10);
montants(1) = 1250.50;
montants(2) = 45.10;
montants(3) = 98000;
montants(4) = 320;
montants(5) = 0;
snd-msg 'Nombre d elements : ' + %char(%elem(montants));
for i = 1 to %elem(montants);
total += montants(i);
endfor;
snd-msg 'Total : [' + %char(total) + ']';
pos = %lookup(320 : montants);
snd-msg 'Position de 320 : ' + %char(pos);
sorta montants;
snd-msg 'Apres tri : ' + %char(montants(1)) + ' / ' + %char(montants(5));
for i = 1 to %elem(villes);
snd-msg 'Ville ' + %char(i) + ' : [' + villes(i) + ']';
endfor;
*inlr = *on;
**ctdata villes
Montpellier
Lyon
Brest
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Nombre d elements : 5
Total : [99615.60]
Position de 320 : 4
Apres tri : .00 / 98000.00
Ville 1 : [Montpellier]
Ville 2 : [Lyon]
Ville 3 : [Brest]
Le tableau montants a cinq éléments : %ELEM le rappelle sans écrire le 5 en dur. %LOOKUP renvoie la position (4) de la valeur 320. Après SORTA, l'élément à zéro passe en tête (affiché .00, voir le piège de %CHAR) et le plus grand en fin. Les villes viennent des lignes **ctdata en fin de source.
Exemple 2 : DIM(*AUTO) : la taille suit l'usage
**free
// DIM(*AUTO : max) : tableau dont la taille suit le nombre d'elements utilises.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s numeros int(10) dim(*auto : 100);
dcl-s i int(10);
snd-msg 'Au depart : ' + %char(%elem(numeros));
for i = 1 to 3;
numeros(i) = i * 100;
endfor;
snd-msg 'Apres 3 affectations : ' + %char(%elem(numeros));
%elem(numeros) = 5;
snd-msg 'Apres %ELEM = 5 : ' + %char(%elem(numeros));
snd-msg 'Element 5 : ' + %char(numeros(5));
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Au depart : 0
Apres 3 affectations : 3
Apres %ELEM = 5 : 5
Element 5 : 0
Au départ, le tableau a zéro élément. Après avoir affecté les indices 1 à 3, il en compte trois. On peut aussi le forcer avec %ELEM(tableau) = 5 : l'élément 5, ajouté, vaut zéro.
Exemple 3 : Indice hors limites
**free
// Piege : un indice hors limites n'est pas controle a la compilation d'une variable.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s montants packed(9:2) dim(3);
dcl-s i int(10);
montants(1) = 10;
montants(2) = 20;
montants(3) = 30;
i = 4;
snd-msg 'Acces a l element ' + %char(i) + ' sur ' + %char(%elem(montants));
snd-msg 'Valeur : ' + %char(montants(i));
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Acces a l element 4 sur 3
Erreur : RNQ0121 - (C G D F) Indice de tableau hors limites.
Le tableau a trois éléments, le programme demande le quatrième : le travail s'arrête sur RNQ0121 (message système MCH0603). La ligne affichant la valeur n'est jamais atteinte.
Exemple 4 : DIM(*VAR) : on fixe la taille soi-même
**free
// DIM(*VAR : max) : la taille s'ajuste, mais seulement quand on la fixe soi-meme avec %ELEM.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s lignes packed(7:2) dim(*var : 20);
dcl-s i int(10);
snd-msg 'Au depart : ' + %char(%elem(lignes)) + ' element';
%elem(lignes) = 4;
for i = 1 to %elem(lignes);
lignes(i) = i * 10;
endfor;
snd-msg 'Apres %ELEM = 4 : ' + %char(%elem(lignes)) + ' / lignes(4) = ' + %char(lignes(4));
%elem(lignes) = 2;
snd-msg 'Apres reduction : ' + %char(%elem(lignes));
lignes(3) = 30;
snd-msg 'Cette ligne ne sera pas affichee';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Au depart : 0 element
Apres %ELEM = 4 : 4 / lignes(4) = 40.00
Apres reduction : 2
Erreur : RNQ0121 - (C G D F) Indice de tableau hors limites.
Contrairement à *AUTO, affecter l'indice 1 d'un tableau vide ne l'agrandit pas : il faut écrire %ELEM(lignes) = 4. On peut aussi réduire la taille ; l'élément 3 devient alors inaccessible et son affectation plante.
Le piège
Un indice hors limites arrête le programme. L'indice se contrôle à l'exécution : montants(i) avec i égal à 4 sur un tableau de trois éléments donne RNQ0121. Contrôlez l'indice avant l'accès (if i >= 1 and i <= %elem(montants)).
Autre limite à connaître : DIM(*AUTO) et DIM(*VAR) sont acceptés sur une zone isolée, mais le compilateur les refuse (RNF3484) sur une sous-zone de structure et sur un paramètre de prototype ou d'interface de procédure. Pour passer un tableau à une procédure, déclarez-le avec sa taille maximale.