%STR
Chaîne terminée par un octet nul
Lit ou écrit, à une adresse donnée, une chaîne de caractères terminée par un octet nul, comme le fait le langage C.
Syntaxe
%STR(pointeur)
%STR(pointeur : longueur-max)
%STR(pointeur : longueur-max) = expression
pointeur- L'adresse de la chaîne.
longueur-max- Nombre maximal d'octets à lire ou à écrire, octet nul compris. Facultatif en lecture.
- Résultat
- En lecture, une valeur caractère de longueur variable contenant le texte jusqu'à l'octet nul (sans celui-ci). En écriture, la fonction est la cible d'une affectation.
À quoi ça sert
Les fonctions du langage C (getenv, strcpy…) et beaucoup d'API IBM i échangent des textes terminés par un octet nul, sans zone de longueur. %STR convertit dans les deux sens : il lit la chaîne à l'adresse reçue, ou écrit la chaîne suivie de l'octet nul.
Exemple 1 : Lire une variable d'environnement, écrire dans un tampon
**free
// %STR : lire et ecrire une chaine C (terminee par un octet nul), comme en API ou en C.
ctl-opt dftactgrp(*no) actgrp(*new) bnddir('QC2LE');
dcl-pr putenv int(10) extproc('putenv');
chaine pointer value options(*string);
end-pr;
dcl-pr getenv pointer extproc('getenv');
nom pointer value options(*string);
end-pr;
dcl-s rc int(10);
dcl-s p pointer;
dcl-s tampon pointer;
dcl-s texte varchar(50);
// Cote C : on cree une variable d'environnement, puis on la relit.
rc = putenv('JOBI_CLIENT=Dupont SA');
p = getenv('JOBI_CLIENT');
texte = %str(p : 50);
snd-msg 'Lu par %STR : [' + texte + ']';
snd-msg 'Longueur : ' + %char(%len(texte));
// Cote RPG : on ecrit une chaine C dans un tampon reserve a la main.
tampon = %alloc(20);
%str(tampon : 20) = 'Montpellier';
snd-msg 'Relu : [' + %str(tampon : 20) + ']';
dealloc(n) tampon;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Lu par %STR : [Dupont SA]
Longueur : 9
Relu : [Montpellier]
getenv renvoie l'adresse d'une chaîne C. %str(p : 50) la convertit : « Dupont SA », 9 caractères. Ensuite on écrit « Montpellier » dans un tampon de 20 octets réservé avec %alloc, et on le relit. Le tampon est rendu à la fin.
Exemple 2 : Longueur maximale et pointeur nul
**free
// %STR : le second parametre limite la lecture, et l'ecriture reserve un octet pour le nul.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s tampon pointer;
dcl-s brut char(12) based(tampon);
dcl-s vide pointer inz(*null);
dcl-s texte varchar(50);
tampon = %alloc(12);
brut = 'ABCDEFGHIJKL';
// Aucun octet nul dans la zone : %STR s'arrete a la longueur maximale.
snd-msg 'Lecture sur 5 octets : [' + %str(tampon : 5) + ']';
snd-msg 'Lecture sur 12 octets : [' + %str(tampon : 12) + ']';
// Ecriture : sur 5 octets, 4 caracteres seulement + l'octet nul.
%str(tampon : 5) = 'Montpellier';
snd-msg 'Apres ecriture sur 5 : [' + %str(tampon : 12) + ']';
snd-msg 'Octet 5 est nul (x''00'') ? ' + %char(%subst(brut : 5 : 1) = x'00');
snd-msg 'Octet 6 inchange : [' + %subst(brut : 6 : 1) + ']';
dealloc(n) tampon;
// Lecture par un pointeur nul.
texte = %str(vide : 10);
snd-msg 'Jamais atteint : ' + texte;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Lecture sur 5 octets : [ABCDE]
Lecture sur 12 octets : [ABCDEFGHIJKL]
Apres ecriture sur 5 : [Mont]
Octet 5 est nul (x'00') ? 1
Octet 6 inchange : [F]
Erreur : MCH3601 - Pointeur non défini pour position mémoire référencée.
La zone ne contient aucun octet nul : %str(tampon : 5) s'arrête à 5 caractères. En écriture avec un maximum de 5, seuls 4 caractères sont écrits (« Mont ») et le cinquième octet vaut x'00'. L'octet 6, plus loin, n'est pas touché. Sur un pointeur nul, le programme s'arrête avec MCH3601.
Le piège
En écriture, la longueur maximale compte l'octet nul. Avec %str(tampon : 5) = 'Montpellier', il reste 4 caractères utiles : « Mont » (exemple 2). Prévoyez toujours un octet de plus que la longueur du texte.
En lecture, si l'octet nul manque, %STR s'arrête à la longueur maximale (exemple 2). Donnez donc toujours une longueur maximale qui borne la lecture.