Cleaning up a string of comma separated account numbers in RPGLE

IBM i

May 16

I was emailed a little IBM i programming question this morning:

An 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 … “.

Mike

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! 🙂

Follow

About the Author

IBM i Software Developer, Digital Dad, AS400 Anarchist, RPG Modernizer, Alpha Nerd and Passionate Eater of Cheese and Biscuits. Nick Litten Dot Com is a mixture of blog posts that can be sometimes serious, frequently playful and probably down-right pointless all in the space of a day. Enjoy your stay, feel free to comment and in the words of the most interesting man in the world: Stay thirsty my friend.