Fun with RPGLE Strings
I was emailed a little IBM i programming question this morning:
An input parameter @Account is a 100 character string for one to
Mike
x number of 8 digit accounts separated with a comma (,). Each
account can be entered with commas between each account.
Example: The string @Account could be “123,00574, 12,142 … “.
Spaces will be converted to zeros, such as “000012”.
The conversion internal in this program will convert this string
as “00000123,00000574,00000012,00000142 … “.
So, I grabbed a coffee, finished my doughnut and wrote this little RPGLE Sub-procedure to take the input string, extract out numbers, neatly format them and return them as a string of 8 character account numbers with leading zeros. hashtag nerdlife.
What is the basic logic?
Let’s write this using an RPGLE array to break each of the account numbers into separate elements, then load each element with only the numbers (1 thru 9) and append a comma as a seperator.
Just for the fun of it, let’s add it as a little sub-procedure to make it easily reusable.
**FREE ctl-opt copyright('| TEST V001 2019.05.16') debug option(nodebugio:srcstmt) datfmt(iso-) timfmt(iso.) indent('| '); dcl-pi *n; parm Char(100); end-pi; // send the input parameter to our number conversion procedure parm = convert_numbers (parm); // end neatly - the new formatted value of "PARM" will be returned *inlr = *on; // +------------------------------------------------------------------------------+ // | convert_numbers | // | The input parameter @Account is a 100 character string for one to | // | x number of 8 digit accounts separated with a comma (,). Each | // | account can be entered with commas between each account. | // | Example: The string @Account could be "123,00574, 12,142 ". | // | Spaces will be converted to zeros, such as "000012". | // | The conversion internal in this program will convert this string | // | as "00000123,00000574,00000012,00000142 ". | // +------------------------------------------------------------------------------+ dcl-proc convert_numbers export; dcl-pi convert_numbers char(100); proc_input Char(100) const; end-pi; dcl-s posn int(10); // count through the 100 positions of the input dcl-s element int(10); // count the elements as we fill them dcl-s rtnval char(100); // final cleaned up value dcl-s numbers char(10) Inz('0123456789'); dcl-ds oneHundredCharacters; char char(10) dim(100); end-ds; monitor; // Read through the variable and extrapolate int numeric 8char elements element = 1; rtnval = proc_input; for posn = 1 to %size(proc_input); //increment to next element when we find a field delimiter ',' // or its the final position if %subst(rtnval:posn:1) = ',' or posn = %size(proc_input); if char(element) <> *blanks; // right adjust and append a seperator[,] evalr char(element) = %trimr(char(element)) + ','; // replacing blanks with ZERO char(element) = %ScanRpl(' ' : '0' : char(element)); //move to next element for the rest of the loop element += 1; endif; // store this character in the next position of the current element // %check - First position in the searched-data that contains a // character not in the list of the characters in the compare value. elseif %check(numbers:%subst(rtnval:posn:1)) = 0; char(element) = %trim(char(element)) + %subst(rtnval:posn:1); endif; endfor; rtnval = oneHundredCharacters; on-error; rtnval = '* Conversion Failed'; endmon; return rtnval; end-proc;
PS: Before leaving any abusive “ahh your code is crappy it could be much smaller” just remember… I will resort to the defense of “I tried to keep the code snippet as simple and readable as possible” 🙂 #lotsofwaystoskinanrpgcat
Testing the RPG Code
CALL PGM(TEST) PARM(' PLOP1, 22, 333, 4444, 55555, 66 6666, 77!7777, 888888, 9e43299,,|,1234ABC')
Note some deliberately DUFF non-numeric characters!
Once the sub-procedure has tinkered with it – these values are returned:
....5...10...15...20...25...30...35...40...45...50...55...60
1 '000000001,000000022,000000333,000004444,000055555,000666666,' 61 '000777777,000888888,000943299,000001234,'
Hope it works for you Mike! 🙂
Now you can do:
Dcl MyArray char(10) dim(08);
MyArray = %list(parm);