S T R U C T O R I Z E R - User Guide
Syntax > Complex Data Types

Arrays

Structorizer supports the use of one-dimensional arrays.

They may be introduced in two ways:

1. Element-wise assignment

As soon as you write an assignment or input instruction and append square brackets with an index expression to the target variable name, the variable will be made an array variable:

names[2] <- "Goofy"

INPUT x[0]

The index range of arrays starts with 0. If you assign something to an array element with larger index than used before, the array will automatically be enlarged up to the new index. If there are index gaps, then the elements inbetween will be filled with 0, e.g. in the first example above, the resulting array names would be filled as follows: {0, 0, "Goofy"}. Note that a reading access with an index larger than the highest index used for assignments or input before will abort the execution with an error message.

2. List initialisation

You may initialise an array variable with a list of element values, enclosed in curly braces (like in C, Java etc.):

values <- {17, 23.4, -9, 13}

friends <- {"Peter", "Paul", "Mary"}

You may combine the initialisation with a declaration in one of several syntactic styles (Pascal or, since version 3.32-04, also Java/C#):

var values: array of int <- {17, 23.4, -9, 13}

string[] friends <- {"Peter", "Paul", "Mary"}

Version 3.24-10 introduced the opportunity to provide such an expression even in the text input field of an executed input instruction, this way making the input variable an array variable:

Input   dialog, filled with an array initialisation

Actually, it is not necessary in Structorizer (though highly recommendable for the processing algorithms), that all elements of an array be of the same type.

Array variables may be passed as arguments to a subroutine (mechanism is call by reference, i.e. changes to the array content will be propagated to and seen by the calling algorithm) and may also be returned as result by a routine.

Array variables (or array expressions) as a whole should not be put into the expression list of an output instruction. If a subroutine executed at top-level returns an array, however, then the array contents will be presented in a scrollable list view. This allows separate testing of subroutines requiring some of its parameters to be an array (on top-level execution, parameter values are asked for interactively, and the input of a value list in curly braces provides an array, see above) or returning an array. The same holds for record variables or expressions.

Array variables or braced value lists (aka array initialisation expressions) are the natural things to be used as collections in FOR loops of the FOR-IN variety, see the FOR loop User Guide page for details.

The following NSD shows some advanced examples of executable and exportable array operations:

Several ways to   work with an array

You may even put entire arrays as elements into other arrays (see fifth instruction in the example diagram above, where one of the elements for array2 is the previously filled array named array). This way, it's possible to construct something similar to a multi-dimensional array, but you will not be able to apply a list (or cascade) of indices to the outer array immediately, say a[i,j] or a[i][j]. Instead, you would have to assign the array held as array element to a simple variable first, e.g. b <- a[i], and may then apply the next index to this variable in order to get to the nested element: b[j].

Strings

Strings are not handled as arrays in Structorizer. (Instead they behave like objects of Java class java.lang.String, because that is what they actually are.) That means: You may obtain the length of a string s either by applying the Java method length() to it — s.length() — or by using the built-in function length(s). Character access via index brackets is not supported. To access a character in a string s, you may either write s.charAt(i) where i counts from 0 to s.length()-1, or you may use the built-in function copy(s, i, 1), which in fact extracts a substring of length 1 (which is not the same as a character, though) at position i where i ranges from 1 to s.length(); you may also have a FOR-IN loop iterate over a string variable (where the loop variable will get actual characters):

Diagram showing three ways to traverse a string

You may not replace a character within the string. You may only form new strings by using the built-in string functions (see reference above) or by concatenating strings with operator +.

Records / Structs

Since release 3.27, Structorizer also supports the use of records (aka structs). Like arrays, records are complex data structures offering the possibility to combine different data within one variable. Unlike arrays, records have got named components, which may explicitly be of different data types. Think of a date of the Gregorian calendar, consisting of a year, a month, and a day number. You might use an array of three numbers in a fixed order for it, but it would be more expressive to access the components via names. The component names and types, of course, must be declared to allow an unambiguous access. Likewise, you might want to combine data about persons, say their name, height, sex, and — hey! — their date of birth. So you should be able to build records on other kinds of records and to give these constructs a unique name.

A type definition syntax was introduced therefore.

Type definitions are to be placed within ordinary elements of Instruction kind, though a type definition doesn't do anything except telling Structorizer how variables of that kind are structured from that element on. The type definition for a record/struct type describes the structure and introduces a user-chosen name for these constructs:

Example for using record types

The first two elements show record type definitions. Each starts with the keyword type, then the name for the type is to be specified, followed by an equality sign and one of the equivalent keywords record or struct and the component declarations within curly braces. Each component must be given a name and should be given a type. The third element of the diagram shows a record variable declaration with initialization via a "record literal" (or say an initialization expression). The initializer looks similar to the type specifications but starts with the previously defined type name instead of struct or record. Instead of component type names now appropriate values must be associated to the field names. The order of the fields may be arbitrary.

The fourth element of the diagram screenshot shows a mere declaration (without initialization), whereas separate component assignments to the otherwise uninitialized variable max follow in the fifth instruction element.

Since version 3.28-06, "smart" record initializers are supported, the item list of which may contain mere expressions — provided their order corresponds to that of the component declarations in the related record type definition. So variable way_back might also have been initialized as shown by the green instruction in the modified diagram snippet below:

extract from the RecordDemo diagram with smart initializer

From the first explicitly occurring component name, however, parsing will ignore all remaining values without component name prefix, such that in the example of the red instruction only components year and month of record partial would be assigned, whereas the value 21 will be ignored. The Analyser report list will show a warning that the day component isn't going to be initialized.

If you pass variables of certain record type as parameters to a subroutine diagram, then a dilemma occurs: Where to place the type definition, such that the parameter structure would be available in both diagrams? In this case, the type definition can only be placed in an Includable diagram, which is then to be included by both the caller and the called diagram.

Enumerators (versions ≥ 3.30-03)

Often you are confronted with a type of data that is to represent one out of a finite and fix set of categories, e.g. the day of week (Monday / Tuesday / Wednesday / Thursday / Friday /Saturday / Sunday) or a university member status (Student / Assistant / Professor) or something the like. Of course you might code these values with integral numbers, but it would be more readable and intelligible if you could use symbolic designations. To use strings instead may be a bad option as it costs more memory and provides only poor options statically to ensure and check the correctness of such a value (e.g. against wrong spelling). Most programming languages therefore provide the concept of so called enumeration types. Actually, an enumeration type is no more than a set of named integer constants that is introduced by enumerating their identifiers.

You may define an enumeration type in Structorizer in the following way:
Prototypical enum type definition

type and enum are reserved words, the identifier between type and = becomes the name of the enumeration type, the identifiers listed between the curly braces are the enumerator constants to be defined. Structorizer assigns consecutive integer codes to the enumerator elements in the listed order, i.e. the first name (e.g. Monday) will be associated with 0, the second one with 1, and so on.

If the coding matters in certain case, then you may explicitly assign a code value to some enumerator identifiers as shown in the orange element of the demo diagram below. The required operator symbol is = , the code must be a constant integer value (ideally a literal, like 42), but may be specified as a simple constant expression i.e. an arithmetic computation from integral constants (integer literals or previously defined constants, including enumerator identifiers) as shown below. Subsequent enumerator elements will be coded incrementally from the explicitly assigned element on.

Simple demo diagram with enumerators