View Full Version : RPGLE IP Adresse formatieren auf 'xxx.xxx.xxx.xxx.'
Hallo Community.
Wir mussten wegen einer Programmanforderung das Format der kompletten
IP Adresse von z. B. 71.6.129.43 (keine Ahnung wer die hat, ist halt ein Beispiel)
so umwandeln das 071.006.129.043 übergeben wird (also mit führenden Nullen auffüllen).
Anbei eine kleine Routine die wir dazu erstellt haben. Vielleicht ist das ja auch für andere
nützlich, deshalb stelle ich das hier mal rein :
D VAR01 S 15a inz('222.55.0.129')
D VAR02 S 15a inz(' . . . ')
D x S 3 0
D y S 3 0
D i S 3 0
D z S 3 0
*
/FREE
Z = 0;
I = 15;
for x = 15 by 1 downto 1;
if %subst(var01:x:1) <> *blanks and %subst(var01:x:1) <> '.';
%subst(var02:i:1) = %subst(var01:x:1);
i = i - 1;
z = z + 1;
endif;
if %subst(var01:x:1) = '.';
for y = z to 2;
%subst(var02:i:1) = '0';
i = i - 1;
endfor;
z = 0;
%subst(var02:i:1) = '.';
i = i - 1;
endif;
endfor;
dsply VAR02;
/END-FREE
c seton LR
Vielleicht hat ja noch jemand "kürzere" Wege. Ich habe auch nach einer %Split BIF Funktion
gesucht aber leider nichts dazu gefunden ...
Kommentare gerne erwünscht.:)
Gruß,
Ralf
Möglichkeiten gibt es wie immer mehrere:
Split kann man mittels %SCAN erreichen. Hier kann man auch eine Startposition angeben.
Per %SUBST dann ab Position mit der Länge den wert entnehmen und das Ergebnis per %DEC in eine Zahl umwandeln.
Per %EDITC(Wert:'X') mit Vornull ausgeben.
// nur Prinzipiell
d MyAdr s 16 varying
d MyIp s 3p 0 dim(4)
d xi s 5i 0
d xp s 5i 0
d xs s 5i 0
myAdr = %trim(var01) + '.'; // für Scan benötigt
xs=1;
for xi=1 to 4;
xp=%scan(xs:'.':myAdr);
myIp(xi) = %dec(%subst(MyAdr:xs:xp-xs));
xs=xp+1;
endfor;
var02 = %editc(myIp(1):'X') + '.' + %editc(myIp(2):'X') + '.' %editc(myIp(3):'X') + '.' %editc(myIp(4):'X');
... Kürze ist nicht das Problem, sondern Lesbarkeit!!!
da macht man sich eine Procedure Num2Alfa3, der eine Zahl übergeben wird und die selbige 3 stellig alfa mit führenden Nullen zurück gibt. Kriegt die Murks schickt sie eine Escape Message. Selbige Procedure gehört dann sogar in ein Standard SRVPGM.
D*B
Hallo.
Ja %editc hatte ich auch kurz drang gedacht aber wie das immer so ist ... man(n) denkt dann einfach zu viel und kommt auf abwege ... :)
Der vorherige Code war noch mal ne Seite länger und ich war schon froh den so "eingekürzt" zu haben ... grins.
Danke nochmals ..
Gruß aus dem düsteren Norden der Republik.
Ralf
Das ist ja ne doofe Anforderung, denn 071.006.129.043 wird manchmal als 57.6.129.35 interpretiert, wegen 0... = oktal.
Wir mussten wegen einer Programmanforderung das Format der kompletten IP Adresse von z. B. 71.6.129.43 (keine Ahnung wer die hat, ist halt ein Beispiel) so umwandeln das 071.006.129.043 übergeben wird (also mit führenden Nullen auffüllen).
@Pikachu : Es gibt ja keine doofen Anforderungen sondern nur intelligente Lösungen :)
Rainer Ross
06-11-14, 23:04
Hallo Forum,
ab 7.1 TR9 oder 7.2 TR1 geht es auch mit der Funktion LPAD in SQL. Ich habe das Beispiel von Baldur Fürchau entsprechend modifiziert
dcl-ds dsmyip;
myip1 zoned(3);
myip2 zoned(3);
myip3 zoned(3);
myip4 zoned(3);
myip zoned(3) dim(4) pos(1);
end-ds;
dcl-s myadr varchar(16);
dcl-s result varchar(16);
dcl-s xi uns(5);
dcl-s xp uns(5);
dcl-s xs uns(5);
clear dsmyip;
myadr = '48.16.0.25';
myadr += '.';
xs = 1;
for xi = 1 to 4;
xp = %scan('.':myadr:xs);
myip(xi) = %dec(%subst(myadr:xs:xp-xs):3:0);
xs = xp + 1;
endfor;
exec sql set :result = lpad(:myip1, 3, '0') concat '.' concat
lpad(:myip2, 3, '0') concat '.' concat
lpad(:myip3, 3, '0') concat '.' concat
lpad(:myip4, 3, '0');
Herzliche Grüße
Rainer Ross
Es fürhren viele Wege nach Rom und obwohl normalerweise ich derjenige bin, der sich für die SQL-Version entscheidet, würde ich an dieser Stelle bei RPG bleiben.
Man kann auch ohne große Konvertierungen (%EditC oder SQL-Funktion) das Ergebnis mit einer entsprechenden Datenstruktur erreichen.
D IPAlt S 15A inz('71.6.129.42')
D DSIPNeu DS
D Arr Overlay(DSIpNeu) Dim(4)
D ArrNum 3S 0 Overlay(Arr) inz(*Zeros)
D ArrChar 3A Overlay(Arr)
D ArrPkt 1A Overlay(Arr: *Next) inz('.')
D IPNeu 15A Overlay(DSIPNeu)
D Index S 3U 0
D NxtPkt S 3U 0
D PrvPkt S 3U 0
************************************************** *********************
/Free
For Index = 1 to %Elem(ArrPkt);
PrvPkt = NxtPkt;
NxtPkt = %Scan('.': IPAlt: PrvPkt+1);
If NxtPkt > *Zeros;
ArrNum(Index) = %Int(%Subst(IPAlt: PrvPkt + 1:
NxtPkt - PrvPkt - 1));
Else;
ArrNum(Index) = %Int(%Subst(IPAlt: PrvPkt + 1));
EndIf;
EndFor;
Dsply ('Alt: ' + IPAlt + ' Neu: ' + IpNeu);
*INLR = *ON;
/End-Free
Wie man's macht ist und bleibt Geschmacksache.
Birgitta
Hallo.
Danke noch mal an alle für die interessanten Lösungswege :)
Ich wünsche allen ein schönes Wochenende.
Ralf
Der Aufruf von SQL ist natürlich ein Overhead. Da ist "%editc(Wert:'X')" erheblich schneller.
Ich bin aber häufiger dafür, durch "intelligente" Definition Arbeitsschritte zu erleichtern.
Da du ja die Felder schon als Zoned definiert hast, sind diese ja bereits Editiert.
Durch kannst myipC char(3) dim(4) pos(1); du dir den Edit sparen.
Durch eine Template-DS, die den Punkt bereits enthält sparst du auch noch den Concat.
Wie immer, es gibt viele Wege.