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 ). 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)
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?
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?
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
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.
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.
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.
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.
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:
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:
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.
Thank you so much, Douglas! It solved my problem
Thank you, everyone! I would mark many answers as Accepted, but unhappily this is not possible, but many of them helped me, thank you
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).