3

In standard RPGLE, my code looks like this. This statement stores the positions of the commas in Data in ComArr array.

C     ','           Scan      Data          ComArr  

I tried doing it in free format like this. But all the indices of ComArr array is loaded with the first position of comma in Data. This is because %Scan returns only one position and upon saving it to an array ends up loading the whole array with a single value.

ComArr = %Scan(',':Data) ;

Is there any other method to process SCAN in free format RPGLE like it does in C spec? Basically I want to split the string separated by a delimiter.

jmarkmurphy
  • 11,030
  • 31
  • 59

2 Answers2

2

One possibility is to keep the C-spec as-is. If the code block needs an array of delimiter positions, and one line of code already does that, put a comment above the fixed-format spec describing what it does and leave it in there.

If /free is required and you don't want to replace the entire block of code, you will need to roll your own loop to build the array of delimiters.

I don't personally convert from fixed to /free unless I am re-writing the block of code to be functionally different. That is, I would almost certainly write a different algorithm in /free than I would have written in fixed. So the entire process of building an array of delimiter positions and then splitting the string based on that array is not something I would do in /free.

I would write a new sub-procedure that returns an array of strings given one delimited input string. The code inside that sub-procedure would make one pass through the input, looking for delimiters with %scan(), and for each one found, split the substring into the next available output array element. There's no need for an array of delimiter positions with this sort of algorithm.

Buck Calabro
  • 7,558
  • 22
  • 25
0

This is probably a little late, but if anyone else needs to split a string by a given delimeter, this code should do what you need.

If you assign a value to an array using wildcard eval array(*) = ..., it applies to every element of the array.

Declare the prototype in your source:

D split           pr          1024a   varying                     
D  string                    65535a   varying const options(*varsize)
D  delims                       50a   varying const               
D  pos                          10i 0

Declare a couple of variables. This assumes your input string is 1000 characters and each separated item is 10 characters maximum:

D idx             s             10i 0
D list            s           1000a
D splitAry        s             10a   dim(100)

This is how you split the string. This tells the routine your delimeter is a comma:

c                   eval      idx = 0                          
c                   eval      splitAry(*) = split(list:',':idx)

Define the procedure that does the work:

 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 * split - Split delimited string                                      
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Psplit            b                   export                           
D split           pi          1024a   varying                          
D  iString                   65535a   varying const options(*varsize)  
D  iDelims                      50a   varying const                    
D  iPos                         10i 0                                  
 *                                                                     
D result          s           1024a   varying                          
D start           s             10i 0                                  
D char            s              1a                                    
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
c                   eval      start = iPos + 1                         
c                   eval      %len(result) = 0                         
 *                                                                     
c                   for       iPos = start to %len(iString)            
c                   eval      char = %subst(iString:iPos:1)            
c                   if        %check(iDelims:char) = 1                 
c                   eval      result = result + char                   
c                   else                                               
c                   leave                                              
c                   endif                                              
c                   endfor                                             
 *                                                                     
c                   return    result                                   
Psplit            e     

Don't forget to add dftactgrp(*no) to your H spec if you're defining and using this in the same module!

Damian
  • 1,652
  • 4
  • 26
  • 44