Building on Last Month's Basics
by Roger Pence
In last month's issue of Midrange Computing, we took a beginning look at tables and arrays. That article focused on defining the different types of tables and arrays and ways to load them with data. This month, we'll dig a little deeper and look at several advanced ways of manipulating array data.
There are six sample programs accompanying this month's article. They are all very short and no test data is required. To load and run any of them, after typing and compiling them, use:
// LOAD// RUN
While the "user-interface" for these programs certainly isn't SAA compliant, you'll get the idea.
Array Specific Operation Codes
RPGII has four array-specific operation codes. Last month, we covered XFOOT, the operation code to sum the value of all elements in a numeric array into a specified field. The other three are SORTA, LOKUP, and MOVEA. Let's take a closer look at each.
The SORTA Operation
SORTA is an array-specific operation code that sorts all elements of an array in ascending or descending order. While there are surely other reasons why you might want an array sorted, SORTA is generally used to ensure that the elements of an array are in the appropriate order for the LOKUP operation code (more on this in a moment).
Column 45 of the array E spec is used to describe the sequence of an array (a "D" indicates the array should be in descending order, an "A" indicates the array should be in ascending order). If no sequence is specified, SORTA sorts the array in ascending order. The code in 1 would sort array ARRY in descending order.
Column 45 of the array E spec is used to describe the sequence of an array (a "D" indicates the array should be in descending order, an "A" indicates the array should be in ascending order). If no sequence is specified, SORTA sorts the array in ascending order. The code in Figure 1 would sort array ARRY in descending order.
If the E spec's column 45 had been blank or an "A", array ARR would have been sorted in ascending order.
For execution-time arrays (an array explicitly loaded with data from your Input or Calc specs), column 45 merely serves as a flag for SORTA to determine the order in which the array should be sorted. But column 45 is really more than a flag for SORTA--an entry in column 45 also tells RPG that the sequence of the array should be checked as it is loaded. Since no data is implicitly loaded for an execution-time array, RPG politely reminds you with a warning error that no sequence checking will be performed for that array. Don't worry, this is just a case of RPG being over-protective. In this case, you only want the entry in column 45 to control the order in which SORTA performs the sort.
If sequence checking is specified for compile-time arrays (arrays loaded with data statements from the source code) or for pre-execution time arrays (arrays implicitly loaded from disk files), the order of the data in the array is checked as it is loaded. If the order is out of sequence as the array is being loaded, a run-time error occurs. It would sure be nice if RPG let these arrays come into the program in jumbled-up order, then allowed you to use SORTA to put them in the right order before you use them, but that is not the case. It is your responsibility to make sure the data for these two types of arrays is in the appropriate sequence before the program starts.
The LOKUP Operation
LOKUP searches an array for a specific value. We saw last month how the LOKUP operation code is used to search for a value in a table (or a pair of tables). Using the LOKUP operation code with arrays requires that:
Factor 1 defines the search value--the value being searched.
Factor 2 defines the array name being searched, and optionally, a beginning array index element.
Unlike table look-ups, factor 3 isn't used with array look-ups.
The resulting indicator in columns 54-59 controls how the look-up is performed. If the array is not sequenced, LOKUP can be used to find a value in the array equal to the search value. To find an equal value, use an indicator in columns 58-59 (equal). If the array is sequenced, either as a result of being loaded that way or having been put in that order with SORTA, LOKUP can also be used to search for:
A value that is greater than the search value by using an indicator in columns 54-55 (high).
A value greater than or equal to the search value by using indicators in columns 54-55 and in 58-59 (high and equal).
A value that is less than the search value by using an indicator in columns 56-57 (low).
A value less than or equal to the search value by using indicators in columns 56-57 and in 58-59 (low and equal).
The RPG manual and some RPG error messages corroborate that anything other than an equal LOKUP requires sequence checking. But RPG is really a little wishy-washy about enforcing this rule, and we'll see an example of bending it to our advantage when we discuss program ARRAY3.
LOKUP really has two "modes" when used with arrays. If an array name without an index is specified in factor 2, LOKUP reports (using the indicator you specified) if the search was successful. For example, the code in 2 would turn on indicator 50 if the value 5 was in any element of array ARR.
LOKUP really has two "modes" when used with arrays. If an array name without an index is specified in factor 2, LOKUP reports (using the indicator you specified) if the search was successful. For example, the code in Figure 2 would turn on indicator 50 if the value 5 was in any element of array ARR.
What if that is not enough information? Not only do you need to know if it's there, but you also need to know where it is. LOKUP provides a way to do this by using the array name with an index. 3 shows an example. This would not only turn on indicator 50 if the value 5 is in the array ARR, but it would also put the element number containing value 5 in X.
What if that is not enough information? Not only do you need to know if it's there, but you also need to know where it is. LOKUP provides a way to do this by using the array name with an index. Figure 3 shows an example. This would not only turn on indicator 50 if the value 5 is in the array ARR, but it would also put the element number containing value 5 in X.
There are two things to be aware of when you use LOKUP in this manner:
1) LOKUP starts the look-up at the element of the specified array index. In the example above, X is set to 1 to start the search in the first element of ARR. Had X been set to 8, LOKUP would have looked for the value 5 in array ARR starting at element 8, disregarding the first 7 elements. This powerful feature is handy because it allows for subsequent searches of other occurrences of the search value. But it's also dangerous--if you forget to set the index value before you start the search, the look-up could return unreliable results.
2) If the LOKUP is successful, the number of the array elements matching LOKUP's criteria is returned in the index field used in factor 2. But, if the search is not successful, this index field is always set to 1. Therefore, you must always use the status of the resulting indicator to ensure the success of the look-up.
SORTA and LOKUP in Action
The sample program, ARRAY1, in 4 demonstrates using SORTA and LOKUP to find the element in an array that is greater than or equal to a specified value. When ARRAY1 starts, it prompts you for values for each of array ARR's 10 elements. After youUve entered these 10 values (you do not have to enter them in sequence), ARRAY1 uses SORTA to sort the array in ascending order. Then, a search is performed for the value you specified and the search results shown, until you enter a zero search value.
The sample program, ARRAY1, in Figure 4 demonstrates using SORTA and LOKUP to find the element in an array that is greater than or equal to a specified value. When ARRAY1 starts, it prompts you for values for each of array ARR's 10 elements. After youUve entered these 10 values (you do not have to enter them in sequence), ARRAY1 uses SORTA to sort the array in ascending order. Then, a search is performed for the value you specified and the search results shown, until you enter a zero search value.
To change ARRAY1 to search for an array element less than or equal to the search value, move indicator 50 in line 13 from columns 54-55 (greater than) to columns 56-57 (less than).
The MOVEA Operation
MOVEA is a very powerful array-specific operation code that can move numeric and alphameric data from fields to arrays, from arrays to fields, or from arrays to arrays. MOVEA is very flexible and provides several ways of moving data, but it does not allow the movement of data from an array to other positions of the same array--the arrays referenced in factor 2 and the result field must always be different arrays.
Data is moved by MOVEA on a byte-per-byte basis, starting at the leftmost position of factor 2 and the leftmost position of the result field. MOVEA stops moving data when either all bytes of factor 2 have been moved or until the last byte of the result field has been filled. 5 shows an example of using MOVEA to move the contents of a 15 character field to a 15 byte, one position element array. If ARR had been defined as having only 10 elements instead of 15, ARR would have the value "Indianapol".
Data is moved by MOVEA on a byte-per-byte basis, starting at the leftmost position of factor 2 and the leftmost position of the result field. MOVEA stops moving data when either all bytes of factor 2 have been moved or until the last byte of the result field has been filled. Figure 5 shows an example of using MOVEA to move the contents of a 15 character field to a 15 byte, one position element array. If ARR had been defined as having only 10 elements instead of 15, ARR would have the value "Indianapol".
Notice how MOVEA stopped moving data when it filled the last byte of ARR. Watch out for this data truncation--MOVEA does its work without regard for array boundaries and will simply assume you want the data chopped off. This is especially critical if youUre moving a numeric source into an alphameric target. If the target isn't sized correctly, you could lose the sign and perhaps some of the digits you meant to move.
MOVEA can also work with an array index to start a move at a particular spot in the array. 6 shows an example. Notice how the first four elements are still blank and the move started in the fifth element. The source data was truncated when the end of array ARR was reached.
MOVEA can also work with an array index to start a move at a particular spot in the array. Figure 6 shows an example. Notice how the first four elements are still blank and the move started in the fifth element. The source data was truncated when the end of array ARR was reached.
MOVEA can also move arrays into fields. Again, the entire array could be moved, or the move could start from a specific element. 7 shows an example. Note how MOVEA stopped moving data when it got to the end of the array ARR. Since it didn't move enough data to fill the last four bytes of FLD, they remain as they were before the MOVEA operation.
MOVEA can also move arrays into fields. Again, the entire array could be moved, or the move could start from a specific element. Figure 7 shows an example. Note how MOVEA stopped moving data when it got to the end of the array ARR. Since it didn't move enough data to fill the last four bytes of FLD, they remain as they were before the MOVEA operation.
MOVEA also allows moving data between arrays. In the example in 8, data is moved from arrays with elements of the same size, but each array has a different number of elements.
MOVEA also allows moving data between arrays. In the example in Figure 8, data is moved from arrays with elements of the same size, but each array has a different number of elements.
And again, with array to array moves, each array can optionally specify an index to indicate where the move should start. 9 illustrates. In this example, the move started from element 2 of array ARR2 and was moved to array AR1, starting with its third element.
And again, with array to array moves, each array can optionally specify an index to indicate where the move should start. Figure 9 illustrates. In this example, the move started from element 2 of array ARR2 and was moved to array AR1, starting with its third element.
In the next example (10), the array elements are different sizes, the array lengths are different, and the arrays are different types. Note how AR2 filled up before all the characters were moved.
In the next example (Figure 10), the array elements are different sizes, the array lengths are different, and the arrays are different types. Note how AR2 filled up before all the characters were moved.
Character Strings
Arrays are especially handy for manipulating character strings. Using the MOVEA operation, a field value can be moved into an array of 1 byte characters, allowing those characters to be manipulated. The modified array could then be moved back into the field with the MOVEA operation code. Three of the sample programs this month show examples of manipulating character strings using several of the concepts weUve discussed so far.
Flipping Two Fields
To be able to search and sort a file alphabetically, it is common to see master files which two name fields: one in the format
To be able to search and sort a file alphabetically, it is common to see master files which two name fields: one in the format
ARRAY2 uses three subroutines
$$FLIP: Returns a flipped name, using the semicolon as the delimiter. If the name doesn't have a semicolon in it, the name is returned unmodified.
$$AT: Returns the position of character in a string. If the character isn't found, a -1 is returned.
$$FFR: Returns the position of the first non-blank character from the right-hand end of a string. If the string is empty, a zero is returned.
To run ARRAY2, type a name in the format
Right or Left Justify a String
The sample program, ARRAY3, in 12, right or left justifies a string. Try typing strings with leading blanks and strings with trailing blanks to see what ARRAY3 does with them.
The sample program, ARRAY3, in Figure 12, right or left justifies a string. Try typing strings with leading blanks and strings with trailing blanks to see what ARRAY3 does with them.
Note that it makes a call to the previously mentioned subroutine $$FFR, to find the first non-blank position from the right-hand end of the string. Several of the subroutines included in these sample programs are designed to be "toolbox" subroutinesQreusable subroutines, separately maintained in their own source files. If youUre familiar with the /COPY concept and compiling programs with the AUTOC procedure, I encourage you to use these subroutines in this fashion (this "toolbox" concept was covered in detail in the November 1988 issue of DataNetwork (now Midrange Computing). If you're not, don't worry about it right now, remove the /COPY line and just use your editor's INCLUDE feature to pull the needed subroutine in.
As we mentioned earlier, by the book, anything but an equal LOKUP requires sequence checking. Line 25 of program ARRAY3 searches an array--without sequence checkingQfor the first non-blank position. This LOKUP causes RPG to wince a little and issue warning error #198, reminding you about sequence checking. Don't worry, this LOKUP does work to find the first non- blank character in an arrayQwithout sequence checking. The moral of the story: just because the rules say it can't be done, doesn't really mean it can't. When you were a kid, how many times did your mother tell you not to eat in the family room? How many times have you done so since without being struck by lightning?
Search and Replace a Character
Given a string, a search character, and a replacement character, the sample program ARRAY4 (13) will search and replace every occurrence of the search character with the replacement character. This program makes a call to $$AT to find the position of a character in a string, so again you need to put that subroutine in this program with your favorite method (remember to remove the /COPY line if you INCLUDE the subroutine).
Given a string, a search character, and a replacement character, the sample program ARRAY4 (Figure 13) will search and replace every occurrence of the search character with the replacement character. This program makes a call to $$AT to find the position of a character in a string, so again you need to put that subroutine in this program with your favorite method (remember to remove the /COPY line if you INCLUDE the subroutine).
Two Dimensional Arrays
RPG's support of arrays is limited to single-dimensional arrays. That is, an RPG array may represent one column and many rows, or many rows and one column, but not many of both. In some cases, it is desirable to "trick" RPG into thinking it can support two-dimensional arrays. Here are two ways to simulate two-dimensional arrays in RPG.
Two-Dimensional Arrays-- Calculation Method
Consider the egg crate example we used last month. An egg crate is a good example of a two-dimensional arrayQit has two rows, with each row containing six columns. If our egg crate was filled with a dozen Easter eggs, sample program ARRAY5 (14) shows you what color Easter egg is in any given row and column. After asking you what row and column you want, ARRAY5 displays the color of the egg at those coordinates.
Consider the egg crate example we used last month. An egg crate is a good example of a two-dimensional arrayQit has two rows, with each row containing six columns. If our egg crate was filled with a dozen Easter eggs, sample program ARRAY5 (Figure 14) shows you what color Easter egg is in any given row and column. After asking you what row and column you want, ARRAY5 displays the color of the egg at those coordinates.
Given the desired row and column, and the total columns in the two- dimensional array, the subroutine $$2DAR calculates what the actual array element number is that matches those coordinates and returns that number in the field @R. To keep this program short, no error checking is performed in $$2DAR. To make this concept really valid, you should add some very robust error checking to $$2DAR (check for logical row and column requests, etc). If an error occurs, $$2DAR should return a -1 in @R to indicate the error condition to the calling code.
While this two-dimensional array trick has some real-world application, I've never really been comfortable with it. Without serious error trapping, it's possible for this technique to cause you more trouble that it's worth. Read on for an alternative method of implementing two-dimensional arrays.
Two-Dimensional Arrays With Nested Arrays
With RPG arrays, array elements cannot be other arrays. At least, that's what RPG thinks. Sample program ARRAY6 (15) shows a technique using the MOVEA operation code that allows an array to be an array of arrays. In program ARRAY6, array HLD is an array with 3000, 20-byte alphameric elements. Array ARR is an array with four, five-digit integer elements. Each element of HLD holds one entire ARR array, therefore, there are actually 3000 ARR arrays available in program ARRAY6! Thinking of the data two-dimensionally, there are 3000 rows available with each row having four columns.
With RPG arrays, array elements cannot be other arrays. At least, that's what RPG thinks. Sample program ARRAY6 (Figure 15) shows a technique using the MOVEA operation code that allows an array to be an array of arrays. In program ARRAY6, array HLD is an array with 3000, 20-byte alphameric elements. Array ARR is an array with four, five-digit integer elements. Each element of HLD holds one entire ARR array, therefore, there are actually 3000 ARR arrays available in program ARRAY6! Thinking of the data two-dimensionally, there are 3000 rows available with each row having four columns.
When program ARRAY6 starts, it asks which copy of array ARR (of the 3000 available) you want to work with. ARRAY6 then asks if you want to add to (A) or show (S) the values in the selected array. When you reply "A", ARRAY6 prompts you for four values to add to the corresponding elements of the currently selected copy of ARR. Use the "A" reply to put several values in several of the available ARR arrays, then use the RSS reply to see that they're really there and that theyUre being correctly incremented. Try entering some negative values to see that the sign of each number isn't lost in the shuffle.
With MOVEA's help, this technique makes the columns (the elements of the nested array) available without any arithmetic and with very little error checking. The MOVEA method offers a more straight-forward and a less error-prone way of implementing two-dimensional arrays in RPG than the previously discussed method.
Using Other Operation Codes
With Arrays
Having seen how SORTA, LOKUP, and MOVEA work with arrays, let's take a look at how some of the non-array specific operation codes work with arrays.
Any of the arithmetic operation codes (MULT, ADD, DIV, Z-ADD, Z-SUB, etc.) can be used with any numeric array or its individual elements. For example, the following code increments the value of the first element of array ARR by 1:
C ADD 1 ARR,1
This code increments the value of ALL elements in array ARR by 1:
C ADD 1 ARR
Notice that no array index is specified in the result field in the second example. Excluding the array index tells RPG to work on every element in the array. This is true for almost all of the arithmetic operation codes (we'll discuss an exception in a moment). When used with an array index, arithmetic operation codes modify that element only; when used without an index, they modify all elements in the array.
Consider an array with 12 nine-digit, two-decimal place numbers. Let's say you wanted to round all 12 elements to 7 digits with no decimal places. The code in 16 would do that.
Consider an array with 12 nine-digit, two-decimal place numbers. Let's say you wanted to round all 12 elements to 7 digits with no decimal places. The code in Figure 16 would do that.
Are Arrays Neat or What?
While most arithmetic operation codes work with an entire array or any individual element in the array, MVR is an exception. MVR, the arithmetic operation code to save the remainder of a division, will not work with all elements of an array at once. To save the remainders of array division, you'll have to use loop-processing as shown in 17.
While most arithmetic operation codes work with an entire array or any individual element in the array, MVR is an exception. MVR, the arithmetic operation code to save the remainder of a division, will not work with all elements of an array at once. To save the remainders of array division, you'll have to use loop-processing as shown in Figure 17.
An alternative method of array division with remainders was discussed in the November 1986 issue of DataNetwork.
You can also MOVE and MOVEL data into an array element or into an entire array. The code in 18 would set the first element of AR1 to an asterisk (*), and all 200 elements of AR2 to asterisks. MOVEL works the same way.
You can also MOVE and MOVEL data into an array element or into an entire array. The code in Figure 18 would set the first element of AR1 to an asterisk (*), and all 200 elements of AR2 to asterisks. MOVEL works the same way.
RPG III offers a feature called multiple-occurring data structures (IBMese for an array of data structures). Using the MOVE operation code with an appropriately sized array and data structure, you can mimic an array of data structures in RPG II (this method is a close cousin to the previously discussed MOVEA two-dimensional array technique).
In the example in 19, HLD is an array that holds 100 "occurrences" of a 32-byte data structure. By MOVEing data back and forth between HLD and the data structure, you can easily mimic an array of data structures. Note that with this construction, either the MOVE operation code or the MOVEA operation code could have been used--both work the same here.
In the example in Figure 19, HLD is an array that holds 100 "occurrences" of a 32-byte data structure. By MOVEing data back and forth between HLD and the data structure, you can easily mimic an array of data structures. Note that with this construction, either the MOVE operation code or the MOVEA operation code could have been used--both work the same here.
Miscellaneous Operation Codes
The four operation codes to move zone and digit portions back and forth (MHHZO, MHLZO, MLHZO, and MLLZO) also work on individual elements of an array or on all of the elements at once. Performing the operation on an array without referencing an index changes every element; specifying an index on the array will cause the operation to affect only the one element.
TESTB, TESTZ, BITOF, and BITON will not work on entire arrays, but may be used with individual elements of an array.
A Bigger Bag of Tricks!
A thorough knowledge of the power of RPG's table and array processing is a very important part of the expert RPG programmer's bag of tricks. In addition to the material we've covered in the last two months, tables and arrays are very thoroughly covered in Chapter 13 of the Programming with RPGII manual. Study that chapter, and fiddle with the sample programs and ideas from this two-part series--you'll need a bigger bag for your RPG tricks before you know it!
Working With Arrays and Tables, Part II
Figure 1 Sorting an array in descending order
Figure 1: Sorting an array in descending order 6..10....+...20....+...30....+...40....+...50...+...60 E ARR 15 10 0D C SORTAARR
Working With Arrays and Tables, Part II
Figure 10 Moving different size arrays
Figure 10: Moving different size arrays 6..10....+...20....+...30....+...40....+...50...+...60 E AR1 5 4 0 E AR2 16 1 C MOVEAAR1 AR2,3 Before MOVEA: Array AR1: /0001/0002/0003/0004/0005/ Array AR2: / / / / / / / / / / / / / / / / / After MOVEA: Array AR2: / / /0/0/0/1/0/0/0/2/0/0/0/3/0/0/
Working With Arrays and Tables, Part II
Figure 11 Flip a name
Figure 11: Flip a Name 1...+...10....+...20....+...30....+...40....+...50...+...60 0001 H 064 Col 75> ARRAY2 0002 ** FLIP A NAME (JONES;BOB = BOB JONES) 0003 FCONIN IP 79 79 KEYBORD 0004 FCONOUT O 79 79 CRT 0005 E W1 30 1 0006 E W2 30 1 0007 C 'NAME' KEY NAME 30 LR 0008 C NLR MOVEANAME W1 0009 C NLR EXSR $$FLIP 0010 C NLR MOVEAW1 NAME 0011 * 0012 C $$FLIP BEGSR 0013 C MOVE *BLANKS W2 0014 C Z-ADD1 X 90 0015 C MOVE ';' CHAR 1 0016 C EXSR $$AT 0017 C X IFNE -1 0018 C ADD 1 X 0019 C MOVEAW1,X W2 0020 C SUB 1 X 0021 C MOVEA*BLANKS W1,X 0022 C Z-ADD30 X 0023 C EXSR $$FFR 0024 C ADD 2 X 0025 C MOVEAW1 W2,X 0026 C MOVEAW2 W1 0027 C END 0028 C ENDSR 0029 * 0030 CSR $$AT BEGSR 0031 C CHAR LOKUPW1,X 50 0032 C N50 Z-ADD-1 X 0033 C ENDSR 0034 * 0035 CSR $$FFR BEGSR 0036 C X DOWNE0 0037 C W2,X IFNE *BLANK 0038 C GOTO $$FFRX 0039 C END 0040 C SUB 1 X 0041 C END 0042 C $$FFRX ENDSR 0043 * 0044 OCONOUT D 1 NLR 0045 O NAME 35 1...+...10....+...20....+...30....+...40....+...50...+...60
Working With Arrays and Tables, Part II
Figure 12 Right or Left justify a character string
Figure 12: Right or Left Justify a Character String 1...+...10....+...20....+...30....+...40....+...50...+...60 0001 H 064 Col 75> ARRAY3 0002 ** RIGHT OR LEFT JUSTIFY A CHARACTER STRING 0003 FCONIN IP 79 79 KEYBORD 0004 FCONOUT O 79 79 CRT 0005 E W1 30 1 0006 E W2 30 1 0007 E RUL 1 1 30 0008 C 'NAME' KEY NAME 30 LR 0009 C 'R/L' KEY RORL 1 LR 0010 C MOVEANAME W1 0011 C Z-ADD30 X 90 0012 C RORL CASEQ'L' $$LJ 0013 C RORL CASEQ'R' $$RJ 0014 C END 0015 C MOVEAW2 NAME 0016 ** 0017 CSR $$LJ BEGSR 0018 C MOVE *BLANKS W2 0019 C Z-ADD1 X 0020 C *BLANK LOKUPW1,X 50 0021 C MOVEAW1,X W2 0022 C ENDSR 0023 ** 0024 C $$RJ BEGSR 0025 C Z-ADDX HOLD 90 0026 C MOVEAW1 W2 0027 C MOVE *BLANKS W1 0028 C EXSR $$FFR 0029 C HOLD SUB X X 0030 C ADD 1 X 0031 C MOVEAW2 W1,X 0032 C MOVEAW1 W2 0033 C ENDSR 0034 ** $$FFR SUBR HERE (INCL FROM ARRAY2 OR /COPY) 0035 C/COPY S,$$FFR 0036 OCONOUT D 1 NLR 0037 O RUL 30 0038 OCONOUT D 1 NLR 0039 O NAME 30 ** (RULER BAR) 1...+...10....+...20....+...30 1...+...10....+...20....+...30....+...40....+...50...+...60
Working With Arrays and Tables, Part II
Figure 13 Earch and replace character string occurences
Figure 13: Search and Replace Character String Occurences 1...+...10....+...20....+...30....+...40....+...50...+...60 0001 H 064 Col 75> ARRAY4 0002 ** SEARCH/REPLACE ALL OCCURRENCES OF CHAR IN A STRING 0003 FCONIN IP 79 79 KEYBORD 0004 FCONOUT O 79 79 CRT 0005 E W1 30 1 0006 C 'NAME' KEY NAME 30 LR 0007 C 'CHAR' KEY CHAR 1 0008 C 'SUB CHAR'KEY SUBCHA 1 0009 C NAME IFNE *BLANKS 0010 C EXCPT 0011 C MOVEANAME W1 0012 C Z-ADD1 X 90 0013 C EXSR $$AT 0014 C X DOWGT0 0015 C MOVE SUBCHA W1,X 0016 C EXSR $$AT 0017 C END 0018 C MOVEAW1 NAME 0019 C EXCPT 0020 C END 0021 ** 0022 ** $$AT SUBR HERE (INCL FROM ARRAY2 OR /COPY) 0023 C/COPY S,$$AT 0024 OCONOUT E 1 0025 O NAME 35 1...+...10....+...20....+...30....+...40....+...50...+...60
Working With Arrays and Tables, Part II
Figure 14 Demonstration of a two-dimensional array
Figure 14: Demonstration of a Two-Dimensional Array 1...+...10....+...20....+...30....+...40....+...50...+...60 0001 H 064 Col 75> ARRAY5 0002 ** TWO-DIMENSIONAL ARRAY DEMO 1 0003 FCONIN IP 79 79 KEYBORD 0004 FCONOUT O 79 79 CRT 0005 E AR1 6 12 7 0006 C 'ROW' KEY R 20 LR 0007 C 'COL' KEY C 20 LR 0008 C NLR Z-ADD6 TCOL 90 0009 C NLR Z-ADD2 TROW 90 0010 C NLR EXSR $$2DAR 0011 C NLR EXCPT 0012 C $$2DAR BEGSR 0013 C TCOL MULT R R 0014 C TCOL SUB C C 0015 C R SUB C R 0016 C ENDSR 0017 OCONOUT E 1 0018 O 5 'ROW=' 0019 O R Z 8 0020 O 15 'COL=' 0021 O C Z 18 0022 O 30 'COLOR=' 0023 O AR1,R 46 ** AR1 (THE EASTER EGGS!) BLUE YELLOW ORANGE BROWN MAGENTAPINK GREEN RED FUSCHIAPURPLE GOLD BEIGE 1...+...10....+...20....+...30....+...40....+...50...+...60
Working With Arrays and Tables, Part II
Figure 15 Two-dimensional array with nested arrays
Figure 15: Two-Dimensional Array with Nested Arrays 1...+...10....+...20....+...30....+...40....+...50...+...60 0001 H 064 Col 75> ARRAY6 0002 ** 2-DIMENSIONAL ARRAYS WITH NESTED ARRAYS 0003 FCONIN IP 79 79 KEYBORD 0004 FCONOUT O 79 79 CRT 0005 E HLD 3000 20 0006 E ARR 4 5 0 0007 C '1-3000 ?'KEY NO 40 0008 C 'A OR S?' KEY FS 1 LR 0009 C NLR FS COMP 'AU 50 0010 C NLR 50 EXSR $$ADD 0011 C NLR FS COMP 'S' 51 0012 C NLR 51 MOVEAHLD,NO ARR 0013 ** 0014 CSR $$ADD BEGSR 0015 C MOVEAHLD,NO ARR 0016 C DO 4 X 20 0017 C X KEY VAL 50 0018 C ADD VAL ARR,X 0019 C END 0020 C MOVEAARR HLD,NO 0021 C ENDSR 0022 ** 0023 OCONOUT D 1 51NLR 0024 O ARR L 60 1...+...10....+...20....+...30....+...40....+...50...+...60
Working With Arrays and Tables, Part II
Figure 16 Rounding all elements of an array
Figure 16: Rounding all elements of an array 6..10....+...20....+...30....+...40....+...50...+...60 E AR1 12 9 2 E AR2 12 7 0 C AR1 MULT 1 AR2 H
Working With Arrays and Tables, Part II
Figure 17 Saving remainders of array division
Figure 17: Saving remainders of array division 6..10....+...20....+...30....+...40....+...50...+...60 E ARR 12 7 0 E REM 12 7 0 C DO 12 X 20 C ARR,X DIV 25 ARR,X C MVR REM,X C END
Working With Arrays and Tables, Part II
Figure 18 Using MOVE on an array
Figure 18: Using MOVE on an array 6..10....+...20....+...30....+...40....+...50...+...60 E AR1 200 1 E AR2 200 1 C MOVE '*' AR1,1 C MOVE '*' AR2
Working With Arrays and Tables, Part II
Figure 19 "Multiple occuring data structure"
Figure 19: "Multiple-occurring data structure" 6..10....+...20....+...30....+...40....+...50...+...60 E HLD 100 32 I DS I 1 20 NAME I 21 262RATE I 27 320DATE I 1 32 ARRDS C** Some code to fill NAME, RATE, and DATE C** and to select X, as the HLD array element in which C** to store the ARRDS data structure. C** C MOVE ARRDS HLD,X C** C** At some other point in the program, here is the C** subsequent code to make the fields from the ARRDS data C** structure previously stored in HLD,5 available: C** C MOVE HLD,5 ARRDS C** C** NAME, RATE, and DATE now have the value that was C** previously stored in HLD,5 6..10....+...20....+...30....+...40....+...50...+...60
Working With Arrays and Tables, Part II
Figure 2 Checking an array for a value
Figure 2: Checking an Array for a Value 6..10....+...20....+...30....+...40....+...50...+...60 C 5 LOKUPARR 50
Working With Arrays and Tables, Part II
Figure 3 Finding the element containing the data
Figure 3: Finding the element containing the data 6..10....+...20....+...30....+...40....+...50...+...60 C Z-ADD1 X C 5 LOKUPARR,X 50
Working With Arrays and Tables, Part II
Figure 4 Sorting arrays and GT/EQ LOKUP
Figure 4: Sorting Arrays and GT/EQ Lokup 1...+...10....+...20....+...30....+...40....+...50...+...60 0001 H 064 Col 75> ARRAY1 0002 ** DEMONSTRATE SORTING ARRAYS AND GT/EQ LOKUP 0003 FCONIN IP 79 79 KEYBORD 0004 FCONOUT O 79 79 CRT 0005 E ARR 10 5 0A 0006 C DO 10 X 40 0007 C X KEY 0008 C END 0009 C SORTAARR 0010 C 'SEARCH' KEY SEARCH 50 0011 C SEARCH DOWNE0 0012 C Z-ADD1 X 0013 C SEARCH LOKUPARR,X 50 50 0014 C EXCPT 0015 C 'SEARCH' KEY SEARCH 0016 C END 0017 C SETON LR 0018 OCONOUT E 1 0019 O ARR Z 70 0020 OCONOUT E 1 0021 O N50 12 'NOT FOUND' 0022 O 50 12 'FOUND ' 0023 O 50 ARR,X Z 25 0024 O 50 X Z 30 1...+...10....+...20....+...30....+...40....+...50...+...60
Working With Arrays and Tables, Part II
Figure 5 Moving a field's contents to an array
Figure 5: Moving a Field's Contents to an Array 6..10....+...20....+...30....+...40....+...50...+...60 E ARR 15 1 C MOVEAFLD ARR Before MOVEA: Field FLD: Indianapolis,IN Array ARR: / / / / / / / / / / / / / / / / After MOVEA: ARR element number: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ARR element value: /I/n/d/i/a/n/a/p/o/l/i/s/,/I/N/
Working With Arrays and Tables, Part II
Figure 6 Starting a MOVEA at a particular element
Figure 6: Starting a MOVEA at a Particular Element 6..10....+...20....+...30....+...40....+...50...+...60 E ARR 15 1 C MOVEAFLD ARR,5 Before MOVEA: Field FLD: Indianapolis,IN Array ARR: / / / / / / / / / / / / / / / / After MOVEA: ARR element number: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 ARR element value: / / / / /I/n/d/i/a/n/a/p/o/l/i/
Working With Arrays and Tables, Part II
Figure 7 Moving arrays into fields
Figure 7: Moving arrays into fields 6..10....+...20....+...30....+...40....+...50...+...60 E ARR 15 1 C MOVEAARR,5 FLD 15 Before MOVEA: Field FLD: XXXXXXXXXXXXXXX Array ARR: /I/n/d/i/a/n/a/p/o/l/i/s/,/I/N/ After MOVEA: Element value: a/n/a/p/o/l/i/s/,/I/N/X/X/X/X/
Working With Arrays and Tables, Part II
Figure 8 Moving data between arrays
Figure 8: Moving data between arrays 6..10....+...20....+...30....+...40....+...50...+...60 E AR1 5 3 E AR2 3 3 C MOVEAAR2 AR1 Before MOVEA: Array AR1: /AAA/BBB/CCC/DDD/EEE/ Array AR2: /TTT/UUU/VVV/ After MOVEA: Array AR1: /TTT/UUU/VVV/DDD/EEE/
Working With Arrays and Tables, Part II
Figure 9 Array to array move with an index
Figure 9: Array to array move with an index 6..10....+...20....+...30....+...40....+...50...+...60 E AR1 5 3 E AR2 3 3 C MOVEAAR2,2 AR1,3 Before MOVEA: Array AR1: /AAA/BBB/CCC/DDD/EEE/ Array AR2: /TTT/UUU/VVV/ After MOVEA: Array AR1: /AAA/BBB/UUU/VVV/DDD/
LATEST COMMENTS
MC Press Online