Wednesday, March 18, 2015

Char built in function added to CL

%char in clp clle and rpg

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:

 

This article was written for IBM i 7.2.

8 comments:

  1. 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.

    ReplyDelete
    Replies
    1. Everyone 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.

      Delete
  2. This is great stuff.......... now if I can only work for a company that is beyond release 6.1

    ReplyDelete
  3. perfect working. i have checked it .

    ReplyDelete
  4. How 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?

    ReplyDelete
    Replies
    1. How about this...

      PGM

      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

      Delete
    2. Thanks Simon.. It saved my time :)

      Delete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.