This page is a lookup for the RPGLE built-in functions that work on arrays. It shows what each one takes, what it returns, and the edge cases that give a zero or a run-time error.
For how arrays are declared, loaded and sorted, read RPGLE Arrays and Tables. The complete list of BIFs is in the RPGLE Built-in Functions Reference.
All examples are free-form RPGLE. Array indexes start at 1.
Array BIFs at a glance
| BIF | What it does | Returns |
|---|---|---|
%elem | Number of elements in an array, table or multiple-occurrence data structure | Unsigned integer |
%size | Size in bytes of a field, or of one array element, or of the whole array | Unsigned integer |
%lookup | Index of the first element that equals a value | Unsigned integer; 0 when not found |
%lookuplt, %lookuple, %lookupgt, %lookupge, %lookupne | Index of an element by comparison with a value | Unsigned integer; 0 when no element matches |
%subarr | A section of an array, starting at an index | An array section |
%ELEM
Returns the number of elements.
%elem(array)
The value is the declared number of elements, so it is the right bound for a loop. It can be used where a numeric constant is allowed in a declaration.
dcl-s nums int(10) dim(5);
dcl-s i int(10);
for i = 1 to %elem(nums);
nums(i) = i * 10;
endfor;
For a varying-dimension array, declared with dim(*auto) or dim(*var), %elem also takes *alloc or *max as a second parameter, and it can be assigned to change the current number of elements.
%SIZE
Returns the number of bytes occupied by a variable or constant.
%size(variable)
%size(array {: *all})
For an array, %size returns the size of one element. With *all it returns the storage taken by every element.
dcl-s codes char(1) dim(7);
// %size(codes) is 1
// %size(codes : *all) is 7
For a varying-length field, %size includes the two or four bytes that hold the current length, so it is larger than the declared maximum length.
%LOOKUP
Searches an array and returns the index of the matching element, or 0 when none matches.
%lookup(arg : array {: start_index {: number_of_elements}})
| Parameter | Meaning |
|---|---|
arg | The value to find |
array | The array to search |
start_index | The first index to search. Defaults to 1 |
number_of_elements | How many elements to search. Defaults to the rest of the array |
%lookup finds an exact match. If several elements match, it returns the index of the first one.
dcl-s letters char(1) dim(7) ascend;
dcl-s idx int(10);
letters(1) = 'A'; letters(2) = 'C'; letters(3) = 'C'; letters(4) = 'C';
letters(5) = 'E'; letters(6) = 'E'; letters(7) = 'G';
idx = %lookup('C' : letters); // 2, the first match
idx = %lookup('C' : letters : 3); // 3, searching from index 3
idx = %lookup('Z' : letters); // 0, not found
%LOOKUP comparison variants
The variants search by comparison. They return the index of the element that is closest to arg in the stated direction, or 0 when there is none.
| BIF | Finds | For arg = 'D' in the array above |
|---|---|---|
%lookuplt | The last element less than arg | 4 |
%lookuple | An exact match, or the last element less than arg | 4 |
%lookupgt | The first element greater than arg | 5 |
%lookupge | An exact match, or the first element greater than arg | 5 |
%lookupne | The first element that does not equal arg | 1 for 'D'; 2 for 'A' |
The words “first” and “last” above are for an array declared ascend. For a descending array the direction reverses, so read the IBM i reference for your array’s order before you rely on the result. Declare the order with ascend or descend on the array so the comparison is made in that order.
idx = %lookupge('D' : letters); // 5, the first element greater than 'D'
idx = %lookuplt('D' : letters); // 4, the last element less than 'D'
idx = %lookupne('A' : letters); // 2, the first element that is not 'A'
%SUBARR
Returns a section of an array. It can be used where an unindexed array is allowed, such as an assignment target or a parameter of %xfoot.
%subarr(array : start_index {: number_of_elements})
start_index must be at least 1 and no greater than the number of elements. If you leave out number_of_elements, the section runs to the end of the array. When you give it, it must be at least 1 and no greater than the number of elements remaining after the start.
dcl-s total int(10);
// nums holds 10, 20, 30, 40, 50
total = %xfoot(%subarr(nums : 2 : 3)); // 20 + 30 + 40 = 90
Choosing a lookup BIF
- Use
%lookupwhen you need an exact match, for example to check that a code is on a list of valid codes. - Use
%lookupgeor%lookupgtwhen the array holds thresholds and you want the first entry at or above a value, for example a rate band. - Use
%lookupleor%lookupltwhen you want the last entry at or below a value. - Use
%lookupneto find the first element that differs from a value, for example the first non-blank entry in an array of blanks. - Pass
start_indexandnumber_of_elementsto search only part of an array, such as the elements loaded so far, so that unused elements do not match.
dcl-s used int(10) inz(3);
dcl-s idx2 int(10);
// search only the first 'used' elements of the array
idx2 = %lookup('E' : letters : 1 : used); // 0, because 'E' is not in elements 1 to 3
Searching only the loaded part of an array
An array always has its declared number of elements, even when you have loaded fewer. Elements that were never assigned hold their initial values, such as blanks or zeros, and a search can match them. Keep a counter of the elements in use and give it to %lookup as the number_of_elements parameter. That limits the search to real data, and it is cheaper than searching the whole array.
Legacy opcodes
Fixed-format code used opcodes for the same jobs. They still compile; use the BIF in new code.
| Fixed-format opcode | Free-form equivalent |
|---|---|
LOOKUP with the EQ indicator | %lookup |
LOOKUP with LT, LE, GT or GE | %lookuplt, %lookuple, %lookupgt, %lookupge |
XFOOT | %xfoot |
Common mistakes
- Using the result of
%lookupwithout testing for 0. - Hard-coding the declared size in a loop instead of using
%elem. - Reading
%sizeof an array as its total storage. Without*allit is the size of one element. - Expecting
%lookupgeor%lookupltto work correctly on an array that is not in the order declared byascendordescend. - Passing a start index or element count that runs past the end of the array to
%subarr.
FAQ
How do I find an element in an RPGLE array?
Use %lookup(value : array). It returns the index of the first match, or 0 when the value is not in the array.
How do I get the number of elements in an array?
Use %elem(array). It is the declared number of elements, or the current number for a varying-dimension array.
What is the difference between %ELEM and %SIZE?
%elem counts elements. %size counts bytes: one element, or with *all the whole array.
Summary
- Learn how to declare and load arrays in RPGLE Arrays and Tables.
- Use the RPGLE Built-in Functions Reference to find the string, numeric and date functions.