IBM i 7.2 introduced a number of new built in functions, BIFs, to CL. One of them is %CHAR, convert to character format. When I found it my first thought was this the same as the RPG %CHAR BIF.
The syntax for the two BIFs is similar:
CL : CHGVAR VAR(&ALPHA) VALUE(%CHAR(&NBR))RPG : Alpha = %char(Nbr) ; |
The CL %CHAR will only convert numeric (*DEC), integer (*INT), unsigned integer (*UINT), and logical (*LGL) data types. The RPG version can do more as it will convert the same data types as the CL BIFs and the date, time, and timestamp types too. So how do they compare for the common data types?
First here is the CL program:
01 PGM 02 DCL VAR(&NBR) TYPE(*DEC) LEN(15 5) 03 DCL VAR(&ALPHA) TYPE(*CHAR) LEN(25) 04 DCL VAR(&INT) TYPE(*INT) 05 DCL VAR(&UINT) TYPE(*UINT) 06 DCL VAR(&LGL) TYPE(*LGL) 07 CHGVAR VAR(&NBR) VALUE(1234.56) 08 CHGVAR VAR(&ALPHA) VALUE(%CHAR(&NBR)) 09 CHGVAR VAR(&NBR) VALUE(-0.5) 10 CHGVAR VAR(&ALPHA) VALUE(%CHAR(&NBR)) 11 CHGVAR VAR(&INT) VALUE(1000) 12 CHGVAR VAR(&ALPHA) VALUE(%CHAR(&INT)) 13 CHGVAR VAR(&UINT) VALUE(5000) 14 CHGVAR VAR(&ALPHA) VALUE(%CHAR(&UINT)) 15 CHGVAR VAR(&LGL) VALUE('1') 16 CHGVAR VAR(&ALPHA) VALUE(%CHAR(&LGL)) 17 ENDPGM |
And now the RPG equivalent. As this is for IBM i 7.2 I am only going to use all free definitions:
01 dcl-s Nbr packed(15:5) ; 02 dcl-s Alpha char(25) ; 03 dcl-s Int int(10) ; 04 dcl-s Uint uns(10) ; 05 dcl-s Lgl ind ; 06 Nbr = 1234.56 ; 07 Alpha = %char(Nbr) ; 08 Nbr = -0.5 ; 09 Alpha = %char(Nbr) ; 10 Int = 1000 ; 11 Alpha = %char(Int) ; 12 Uint = 5000 ; 13 Alpha = %char(Uint) ; 14 Lgl = '1' ; 15 Alpha = %char(Lgl) ; 16 *inlr = *on ; |
So how do they compare?
CL | RPG | |||
To convert | Line | Output | Line | Output |
0000001234.56000 | 8 | '1234.56000' | 7 | '1234.56000' |
-0000000000.50000 | 10 | '-.50000 ' | 9 | '-.50000 ' |
1000 | 12 | '1000 ' | 11 | '1000 ' |
5000 | 14 | '5000 ' | 13 | '5000 ' |
'1' | 16 | '1 ' | 15 | '1 ' |
The results are identical!
So what does RPG's %CHAR do with dates, times, and timestamps?
01 dcl-s Alpha char(30) ; 02 dcl-s TS timestamp inz(*sys) ; 03 dcl-s D date inz(*sys) ; 04 dcl-s T time inz(*sys) ; 05 Alpha = %char(TS) ; 06 Alpha = %char(D:*iso) ; 07 Alpha = %char(D:*mdy) ; 08 Alpha = %char(T:*usa) ; 09 Alpha = %char(%subdt(TS:*y)) ; 10 Alpha = %char(%subdt(TS:*m)) ; |
The results are:
Line | Result |
5 | 2015-03-11-04.14.19.126000 |
6 | 2015-03-11 |
7 | 03/11/15 |
8 | 04:14 AM |
9 | 2015 |
10 | 3 |
The INZ(*SYS) on lines 2 – 4 are used to initialize the variables with the current timestamp, date and time. For more information on this see Initializing variables with special values.
The %SUBDT BIF, on lines 9 and 10, is used to extract portions of a date, time, or timestamp. On line 9 I am extracting the year, *Y or *YEAR, from the timestamp variable. On line 10 the month, *M or *MONTH. The result of the %SUBDT is a number, therefore, when the %CHAR is used on the result the leading zero of the month is removed.
When I want to keep the leading zeroes when I convert a numeric to an alphanumeric variable I use the %EDITC BIF:
01 dcl-s Nbr1 packed(15:5) ; 02 dcl-s Nbr2 packed(7) ; 03 Nbr1 = 1234.56 ; 04 Alpha = %editc(Nbr1:'Q') ; 05 Alpha = %editc(Nbr1:'X') ; 06 Nbr1 = 123 ; 07 Alpha = %editc(Nbr1:'Q') ; 08 Alpha = %editc(Nbr1:'X') ; 09 Nbr2 = Nbr1 ; 10 Alpha = %editc(Nbr2:'X') ; |
The results look like:
Line | Result |
4 | 1234.56000 |
5 | 000000123456000 |
7 | 123.00000 |
8 | 000000012300000 |
9 | 0000123 |
I use the edit code 'Q' when converting a number with decimal places, and 'X' for one with no decimals.
While the CL %CHAR BIF can only be used in IBM i 7.2, everything else I have described will work for V5R1 and greater.
You can learn more about these on the IBM website:
- CL %CHAR
- RPG %CHAR for numbers
- RPG %CHAR for dates, times, timestamps
- RPG %EDITC
- RPG %SUBDT
- Edit codes
This article was written for IBM i 7.2.
I like your posts. I don't say so for each one because that would be cloying, but I think they are well written, concise, and practical. Keep up the good work.
ReplyDeleteThank you!
DeleteEveryone has their own flavor depending on their nature of profession. Simon is a full time developer, and therefore writes articles as he experiences problems and/or thinks of new tricks. That makes it relatable to us.
DeleteThis is great stuff.......... now if I can only work for a company that is beyond release 6.1
ReplyDeleteperfect working. i have checked it .
ReplyDeleteHow do you keep leading zeros in CL programming? I'm looking for the CL equivalent of %editc but am coming up empty handed. Am I the only one that's ever needed to convert decimal to char and keep leading zeros in CL programming?
ReplyDeleteHow about this...
DeletePGM
DCL VAR(&NBR) TYPE(*DEC) LEN(5 2)
DCL VAR(&CHAR) TYPE(*CHAR) LEN(8)
CHGVAR VAR(&NBR) VALUE(123.45)
CHGVAR VAR(&CHAR) VALUE(&NBR)
ENDPGM
Thanks Simon.. It saved my time :)
Delete