How to read/iterate the data in Array (1:V)

Hello. Recently discovered this way of passing array data from a program to a subprogram (using an ARRAY(1:V)). I’m trying to use it, but couldn’t find how to iterate through the data received in the subprogram using this array… All options I could imagine (FOR, REPEAT…) need a stop criteria. I tried to search it in documentation, but couldn’t find this info (that’s why I’m here :slight_smile: ). I’m using natural on mainframe. Can anyone help me?

In the PROGRAM I have:

LOCAL
1 IND            (N02)  CONST <127>
1 DATA-ARRAY     (1:IND)
   2 DATA-1      (N1)
   2 DATA-2      (N2)

In the SUBPROGRAM, I have:

PARAMETER
1 ARRAY (1:V)
   2 DATA-1    (N1)
   2 DATA-2    (N2)

The thing is that there may be less than 127 occurrances. I Tried this, but it’s not permited.
FOR #INDEX 1 TO V

How can I iterate through the quantity of occurrrences received through the array in the subprogram (if it is less than 127)?

Thanks in advance.

Sample code.

LOCAL
1 #OCC (I4)
1 #INDEX (I4)
END-DEFINE
ASSIGN #OCC = *OCC (DATA-1)
FOR #INDEX = 1 #OCC
1 Like

Amzing!
And in the case which not of all occurrences are filled with data? For example, an array with capacity 127, but only 3 occurrences have data stored?

Send only the filled entries. The count will vary, hence the (1:V).

DEFINE DATA LOCAL
1 #MAX (I4) CONST <150>
1 #ARRAY (1:#MAX)
  2 DATA-1 (N1)
  2 DATA-2 (N2)
1 #I (I4)
END-DEFINE
* ...
  ADD 1 TO #I
  IF  #I > #MAX
    THEN
      WRITE 'array exceeded'
      STOP
  END-IF
  ASSIGN DATA-1 (#I) = 1
  ASSIGN DATA-1 (#I) = 2
* ...
CALLNAT "SUBPGM" #ARRAY (1:#I)
END
1 Like

Thanks for reply! In your example, I have to read until the maximum size (150).
But in case I don’t know the amout of occurrences filled with data I’m going to receive, and just want to work/read/process them? For example: I have only 3 occurrences filled with data, how can I read only this 3, if I don’t kow previously, the amount? I can receive 5, 50 or 500, but I don’t know, it 's not fixed… There’s a solution for that?

Priscilla,

In Ralph’s example, he is only passing #ARRAY (1:#I) to the subprogram. Since your subprogram’s array is defined as ARRAY(1:V), it will only have #I occurrences. To determine how many occurrences, use *OCC(DATA-1). Here is an example, putting it all together:

Program:

DEFINE DATA LOCAL                          
1 IND            (I4)  CONST <127>         
1 DATA-ARRAY     (1:IND)                   
   2 DATA-1      (N7)                      
   2 DATA-2      (N7)                      
1 #I  (I4)                                 
1 #IX (I4)                                 
END-DEFINE                                 
*                                          
FOR #I = 1 TO 20                           
  ADD 1 TO #IX                             
  MOVE #IX TO DATA-ARRAY.DATA-1(#IX)       
  COMPUTE DATA-ARRAY.DATA-2 (#IX) = #IX * 2
END-FOR                                    
*                                          
CALLNAT 'ARRAY' DATA-ARRAY(1:#IX)       
*                                          
END                                        

Subprogram ARRAY

DEFINE DATA                     
PARAMETER                       
1 ARRAY (1:V)                   
   2 DATA-1    (N7)             
   2 DATA-2    (N7)             
LOCAL                           
1 #OCC (I4)                     
1 #INDEX (I4)                   
END-DEFINE                      
*                               
ASSIGN #OCC = *OCC (DATA-1)     
WRITE '=' #OCC                  
*                               
FOR #INDEX = 1 #OCC             
  DISPLAY #INDEX                
          ARRAY.DATA-1 (#INDEX) 
          ARRAY.DATA-2 (#INDEX) 
END-FOR                         
*                               
END                             

Copy these modules into a test library and give them a spin.

1 Like

to use a dynamic array in the calling program, you can use this program:

DEFINE DATA LOCAL                          
1 DATA-ARRAY     (1:*)                   
   2 DATA-1      (N7)                      
   2 DATA-2      (N7)                      
1 #I  (I4)                                 
1 #IX (I4)                                 
END-DEFINE                                 
*                    
resize array data-array to (1:127)                      
FOR #I = 1 TO 20                           
  ADD 1 TO #IX                             
  MOVE #IX TO DATA-ARRAY.DATA-1(#IX)       
  COMPUTE DATA-ARRAY.DATA-2 (#IX) = #IX * 2
END-FOR                       
*
resize array data-array to (1:#IX)
*                                          
CALLNAT 'ARRAY' DATA-ARRAY(*)       
*                                          
END                                        
             

note that the initial size of 127 is arbitrary here, copied from Jerome’s example.

With a dynamic array being passed to the called subprogram, it is possible for the called subprogram to add (or remove) occurrences to the array - this is typically used when the subprogram is loading the data to return to the calling program) by using the resize/expand/reduce statements.

1 Like

Thanks for replying, Jerome! Where did this 20 (in FOR #I = 1 TO 20 ) come from? Or is it just arbitrary? It would be the amount of filled occorrences?
Thanks in advance.

Yes, 20 is just an arbitrary quantity to represent the data being sent (perhaps from a FIND or READ loop), giving the number of filled occurrences. Jerome’s array has an upper limit of 127, mine is expandable from the program with new ranges calculated for the RESIZE ARRAY statement - the “to (1:127)” could also be variable or further RESIZE ARRAYs could be executed inside the loop that is loading data to expand the array size as needed.

2 Likes

Yes, it was arbitrary so you could see that the array size in the subprogram matches the occurrences being passed by the calling program. I often write little test programs for functionality that I am not familiar with so I can play with it and see how it works.

1 Like

If you use a dynamic array, you can increase the size as you add entries. Then it will be without empty entries and *OCC(DATA-1) will give you the exact size.

1 Like

Hi Jerome, thanks for your reply! But I’m with a problem…
I have a PROG that receives data from the web application, and then the program passes this data to the SUBPROGRAM. I can receive 1 or more registers of PHONES from the web app . In my PROG I have this in as data entry:

> 1 #MAX             (N02) <100>
> *
> 1 #ENTRY-DATA-PROGRAM
>   2 #NAME
>   2 #ADRESS
>   2 #PHONES        (1:#MAX) 
>      3 #DDD        (N03)
>      3 #NUMBER     (N09)

When I read the data, I do it in a FOR loop verifing from 1 to 100 if #DDD and #NUMBER have values. If they’re 0, I don’t load the fields that are entry for the subprogram, like this:

FOR #I 1 #MAX
IF #DDD =0 AND #NUMBER = 0
ESCAPE BOTTOM
END-IF

MOVE #DDD TO #DDD-SUBP
MOVE #NUMBER TO #NUMBER-SUBP
END-FOR

Im testing, with 2 register on entry, so in for loop, only 2 occurrences are loaded. When I call my SUBPROGRAM, I have this on entry:

> 1 #ENTRY-DATA-SUBP
>   2 #NAME-SUBP
>   2 #ADRESS-SUBP
>   2 #PHONES-SUBP     (1:V) 
>      3 #DDD-SUBP     (N03)
>      3 #NUMBER-SUBP  (N09)

Before processing the data in a FOR loop, I’m trying to obtain the amount of occurrences received with *OCC:

#AMOUNT-REGISTERS := *OCC (#PHONES-SUBP)

but I don’t know why it is returning to me 100 in #AMOUNT-REGISTERS… I really don’t and I don’t understand why it isn’t returning 2, because when I tested in a simple program this *OCC returned the amount of filled occurrences… Can anybody help me?

Since #PHONES array in the program is a fixed array, it always has 100 occurrences. If you change the program data definition to #PHONES (1:*) and add
EXPAND ARRAY #PHONES TO (1:#MAX) before the FOR loop and after the FOR loop
RESIZE ARRAY #PHONES TO (1:#I)
then *OCC in the subprogram will contain the actual occurrences in use.

1 Like

Thank you so much, Douglas! It solved my problem :slight_smile:
Thank you, everyone! I would mark many answers as Accepted, but unhappily this is not possible, but many of them helped me, thank you :+1:

Priscilla,

The (1:V) syntax was available long before X-arrays (i.e. (1:*)). X-arrays incur overhead and should be used only when necessary. They are not necessary in your example.

If *OCC is 100, then you must be passing 100 occurrences. I am guessing that your program is passing #PHONES (1:#MAX). It should be passing #PHONES (1:#I).