Converting Alpha to Numeric
My AS/400 is receiving data from a shipping system through an ODBC connection. My RPG III (RPG/400) program needs to convert a nine-byte alphanumeric field to a number. The alpha field may contain zero or more digits, a decimal point, and two digits. How can I convert the alpha field to a number?
There are quite a few ways to convert alpha strings to numbers, Duane.
In your case, the easiest way is to let CL do the conversion. The Change Variable (CHGVAR) command can convert an alpha string to a packed decimal value. The alpha string can contain leading and/or trailing blanks, a leading hyphen for negative numbers, and a decimal point, which may be either a period or a comma.
Here's the program to convert the data.
PGM PARM(&IN &OUT &RTNCD) DCL VAR(&IN) TYPE(*CHAR) LEN(17) DCL VAR(&OUT) TYPE(*DEC) LEN(15 2) DCL VAR(&RTNCD) TYPE(*CHAR) LEN(1) CHGVAR VAR(&RTNCD) VALUE('0') CHGVAR VAR(&OUT) VALUE(&IN) MONMSG MSGID(CPF0818) EXEC(DO) CHGVAR VAR(&RTNCD) VALUE('1') ENDDO RETURN ENDPGM
The program returns a non-zero value in the third parameter if the input value is not convertible. An RPG III program would call the program this way:
C CALL 'NUM001CL' C PARM ALPHA 17 C PARM NUM 152 C PARM RTNCD 1
I have never had a performance problem with little programs like this, even though the CL program activates and deactivates on each call. If performance is a problem, you'll need to write an RPG routine to handle the conversion. I have used a method that I leaned in an assembly language class ages ago. It's based on Horner's Method, a way of expressing a polynomial without exponentiation. Here's the general idea.
C MOVE *ZERO ACCUM 150 C 1 DO 9 X 30 C SUBSTALPHA:X CHAR 1 C MOVE CHAR DIGIT 10 C MULT 10 ACCUM C ADD DIGIT ACCUM C ENDDO
You would have to beef up this code to handle invalid data, ignore leading and trailing blanks, and handle a decimal point.
If you can manage to get into the exciting world of ILE, you have more options.
If you are at V5R2, you can pass character strings to the %DEC, %DECH, %INT, %INTH, %UNS, %UNSH, and %FLOAT built-in functions. If the character string contains invalid data, the system ostensibly generates an exception with status code 105.
D Alpha s 17 D Num s 15p 2 D ValidData s n D /free ValidData = *on ; monitor ; num = %dec(Alpha:15:2) ; on-error 105 ; ValidData = *off ; endmon ; /end-free
I say "ostensibly" because you can't monitor for the 105 exception yet. There's a bug in the compiler that prevents you from listing error 105 in the on-error op code. I've reported it to IBM and I'm sure they'll have a PTF for it before long. Therefore, the above example has been not been tested with the monitor in place.
I'm not a fan of C, but binding the C run-time function atof is another possibility, as the following example shows.
D Alpha s 17 D Num s 15p 2 D atof pr 8f extproc('atof') D * value options(*string) /free num = %dech (atof (Alpha):15:2) ; *inlr = *on ; /end-free
Alpha contains the number to be converted. The options(*string) option terminates Alpha with a null character, as C requires of character strings. The num variable will be zero if Alpha contains invalid data.
I do not like this method because I do not like floating-point arithmetic. If you use atof, be sure to half-adjust the result, as I have done in this example. If you don't, the extracted number may not match the string. I also do not like the fact that invalid data returns a zero.
You can also use the Convert External Form to Numeric Value (cvtefn) MI library functions. I have played with them, and I consider them to be more trouble than they are worth.
Now that I've shared different ways to accomplish your task, let me tell you how I would handle this challenge. My preference would be to compile the CL source code in the first example into a module, which I would bind into an ILE program along with my RPG module. That would let me call the CL routine as a procedure, eliminating the overhead associated with calling a CL program. Only if performance were not acceptable would I consider another solution.
Contact the Editors
|Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.|