Variable type ARRAY

An array is a variable consisting of any number of variables (elements) of same type that are accessed by index. You can use safe arrays (read in this topic), pointer-based arrays, embedded arrays, string map and CSV.

 

A variable of type ARRAY is an OLE-Automation-compatible dynamic (resizable) multi-dimensional (1 to 10 dimensions) safe array.

 

When declaring a variable of type ARRAY, you also must specify the type of elements. Syntax:

 

ARRAY(type) var

 

type - any type except ARRAY.

var - variable name.

 

To access an element, use syntax:

 

arr[i1 [i2 ...]]

 

arr - variable of type ARRAY.

i1 - element index in leftmost dimension (dimension 1).

i2 - element index in dimension 2, etc.

 

Error if the index is invalid (the element does not exist).

 

There are several functions and other ways to add elements. Read about it later in this topic.

 

Examples:

 

ARRAY(str) a ;;declare array of strings
a.create(10) ;;add 10 empty elements
a[0]="first element" ;;set first element
str s
s=a[0] ;;assign value of first element to a variable
out s

ARRAY(str) am.create(3 10) ;;2 dimensions, 3 elements in first dimension, 10 in second
int i j
for i 0 am.len(2) ;;enumerate dimension 2
	for j 0 am.len(1) ;;enumerate dimension 1
		am[j i].from(j " " i)
		out am[j i]

 

To add one element to a 1-dimension array and assign a value, can be used empty []. Examples:

 

int i
ARRAY(int) a
for(i 0 10) a[]=i ;;adds and sets 1 element
for(i 0 a.len) out a[i]

ARRAY(str) b
for(i 0 10) b[].from("element " i) ;;adds and sets 1 element
for(i 0 b.len) out b[i]

ARRAY(str) c
for(i 0 10)
	str& s=c[] ;;adds 1 element and gets reference to it
	s.from("element " i)
	s+" in array c"
for(i 0 c.len) out c[i]

ARRAY(POINT) d
for(i 0 10)
	POINT& p=d[] ;;adds 1 element and gets reference to it
	p.x=i; p.y=i*2
for(i 0 d.len)
	&p=d[i]
	out F"{p.x} {p.y}"

 

To populate a string array with multiple values, you can assign a multiline string. You also can assingn array to a str variable. Examples:

 

ARRAY(str) a="zero[]one[]two"
int i
for(i 0 a.len) out "%i %s" i a[i]

str s=a
out s

 

ARRAY variables are freed automatically. If you need to explicitly remove all elements, assign 0 or call redim without arguments:

 

a=0
 or
a.redim

 

More details

ARRAY can be used in user-defined types, but cannot be used in embedded arrays. Example:

 

type ABC int'x ARRAY(BSTR)'a

 

ARRAY can be passed to functions. When passing to a user-defined function, whole array is copied, unless it is passed by reference (address of ARRAY variable). Arrays are not copied when passing to other functions (not user-defined). COM functions usually accept SAFEARRAY*, which is the same as ARRAY, therefore ARRAY variable can be simply passed. Dll functions that accept arrays usually expect direct pointer to array data (not ARRAY or SAFEARRAY*). Then you can pass address of first element (e.g., &arr[0]).

 

A variable of type ARRAY actually is pointer (4 bytes) to array descriptor. The array descriptor (variable of type SAFEARRAY), along with other properties, holds the pointer to the actual data. All memory allocation is managed automatically.

 

ARRAY is compatible with Visual Basic dynamic array. However, elements of multidimensional array are stored differently than in C or Pascal arrays. For example, ARRAY(int) a.create(x y) creates array that by storage order is equivalent to C array declared as int a[y][x], that is, order of dimensions is reverse.

 

ARRAY type supports operator = (assign). When you assign one array to another, whole array is copied, including all associated data.

 

You can also assign string (str, lpstr or BSTR) to array of str or BSTR type. Result will be single-dimensional array of strings where each string is one line from source string. If you assign single-dimensional array of strings to str or BSTR variable, result will be string where every line is element of source array. If array is multidimensional, result will be string where all elements are joined.

 

Array also can be assigned to variable of type VARIANT. When VARIANT variable is destroyed, or type is changed, containing array is freed. If you use operator =, array is copied. If you use function attach on VARIANT variable, it stores array into that variable, and sets ARRAY variable to 0.

 

To declare a global variable or pointer to ARRAY, etc, use appropriate characters after the closing parenthese. Examples:

 

ARRAY(str) as ;;array of str variables
ARRAY(int)+ ai ;;global array of int variables
ARRAY(VARIANT) av ;;array of VARIANT variables. VARIANT can contain other data types, therefore we can say that array element types can be different.
ARRAY(RECT) ar ;;array of RECT variables
ARRAY(RECT*) arp ;;array of pointers to RECT variables
ARRAY(int)* pai = &ai ;;pointer to array of int variables

 

Functions

Here var is variable of type ARRAY. If a return type is not specified, the function returns var itself.

 


 

var.create([n1] [n2 ...])

 

Creates and initializes array.

 

n1, n2, ... - number of elements in each dimension.

 

This function also can be used to resize array without preserving previous content.

 

If called without arguments, creates array descriptor but does not allocate memory for elements.

 


 

var.createlb(n1 lb1 [n2 lb2 ...])

 

Same as create, but allows you to specify lower bounds.

 

lb1, lb2, ... - lower bound (index of first element) of each dimension. Can be negative.

 


 

int var.redim([n] [lb])

 

Resizes rightmost dimension. If the array is not created, creates 1-dimension array.

 

n - new number of elements. Negative n will add -n elements.

lb - new lower bound. If lb is omitted, does not change it.

 

If array is growing, returns index of the first added element (rightmost dimension). If shrinking, the return value is undefined.

 

The function preserves elements that exist in both old and new arrays.

 

If called without arguments, frees the array and sets var to 0. Other way to free array - assign 0 (a=0).

 


 

int var.insert(index)

 

Inserts new empty element. If the array is not created, creates 1-dimension array.

 

index - element index. If it is index of last element + 1, adds to the end.

 

Returns index.

 

Supports multi-dimension arrays. Inserts in the rightmost dimension. For example, if the array has 2 dimensions, where the first used for columns and the second for rows, the function inserts new row.

 

Added in QM 2.3.2.

 


 

var.remove(index)

 

Deletes an element.

 

index - element index.

 

QM 2.3.2. Supports multi-dimension arrays. Removes from the rightmost dimension. For example, if the array has 2 dimensions, where the first used for columns and the second for rows, the function removes whole row.

 

Note: When removing elements in for loop, start from the end. Example:

 

ARRAY(str) a="a[]b[]c[]d[]e"
int i; for(i a.len-1 -1 -1) if(i&1) a.remove(i)
out a

 


 

int var.len([dim])
int var.lbound([dim])
int var.ubound([dim])

 

len returns the number of elements.

lbound returns index of the first element.

ubound returns index of the last element.

 

dim - 1-based dimension index. Default: rightmost dimension.

 


 

int var.ndim

 

Returns the number of dimensions.

 


 

var.sort([flags] [sortfunction] [param])

 

Sorts array elements.

 

flags:

1 Sort descending. This flag also is applied when using sort function.
2 Case insensitive.
4 QM 2.3.2. Linguistic. Uses StrCmp to compare strings.
8 QM 2.3.2. Number, linguistic, case insensitive. Uses StrCmpLogicalW to compare strings. It compares numbers in strings as number values, not as strings.
0x100 (flag) QM 2.3.3. Date. Converts strings to DATE and compares. If cannot convert both strings, compares like without this flag.

Flags 2, 4 and 8 used with str and lpstr arrays, when sortfunction not used. If without flags 4 and 8, uses StrCompare to compare strings.

 

sortfunction - name of a user-defined callback function. Required only if type of array elements is not str, lpstr, int, byte, word, double, long.

param - some value to pass to the sort function. Default: 0.

 

The callback function is used for custom sorting. It is called multiple times while sorting, and must compare two elements in the array.

 

A template is available in menu -> File -> New -> Templates.

 

The function must begin with:

 

function# param TYPE&a TYPE&b

 

param - param of sort.

TYPE - type of array elements.

a, b - two array elements.

 

The callback function must compare a and b, and return:

 

Example:

 

 sorts multiline string
str s="zero[]one[]TWO[]THREE"
ARRAY(str) a=s
a.sort(2)
s=a
out s

 

QM 2.3.2. Supports multi-dimension arrays. Sorts rightmost dimension.

 

When sorting multi-dimension array, compares first element for each indice of rightmost dimension. For example, if the array has 2 dimensions, where the first used for columns and the second for rows, the function compares the first element in each row. When using callback function, the function receives reference to that element. To compare other element, adjust references as in the example.

 

function# param str&a str&b

 initially a and b are elements in column 0
&a=&a+(2*sizeof(a))
&b=&b+(2*sizeof(b))
 now a and b are elements in column 2

 ...

 


 

var.shuffle

 

Shuffles (randomizes) array elements.

 

QM 2.3.2. Supports multi-dimension arrays. Shuffles rightmost dimension.

 

Notes

ARRAY functions are not thread-safe. Don't use a single variable in multiple threads simultaneously. It can damage data. If need to use in multiple threads, use lock.