Feldgruppen

Die Regeln für eine EGL-Feldgruppe richten sich nach dem Feldgruppentyp.

EGL unterstützt folgende Arten von Feldgruppen:

In allen Fällen werden maximal sieben Dimensionen unterstützt.

In EGL hat das erste Element in einer Feldgruppe den Index 1. In vielen Programmiersprachen hat das erste Element den Index 0.

Feldgruppenliterale

Ein Feldgruppenliteral besteht aus einer einleitenden eckigen Klammer gefolgt von einer durch Kommas unterteilten Liste von Literalen (einschließlich anderer Feldgruppenliterale) oder Ausdrücken (einschließlich von Feldgruppenvariablen) und einer abschließenden eckigen Klammer. Jedes einzelne Feldgruppenliteral weist einen Typ auf und kann überall dort verwendet, wo eine Feldgruppe des betreffenden Typs zugelassen ist (z. B. als Initialisierungsoperator für eine Feldgruppenvariable). Die folgende Tabelle enthält Beispiele für Feldgruppenliterale:

Tabelle 1. Feldgruppenliterale
Feldgruppenliteral Typ
[ 1, 2, 3 ] SMALLINT[]
[ "hi", "Mom" ] STRING[]
[ new myRecord, new myRecord ] myRecord[]
[ (myPay < 0), (myPay > 0) ] BOOLEAN[]
[ [ 1, 2 ], [ 3, 4 ] ] SMALLINT[][]
[ 3, "cow", [ 4.5, 6.7 ] ] ANY[]

Weichen die Typen der Elemente im Feldgruppenliteral voneinander ab, ergibt sich als Typ der Feldgruppe der Typ ANY. Die Elemente in der Feldgruppe müssen nicht untereinander zuordnungskompatibel sein.

Dynamische Feldgruppen

Die Deklaration einer dynamischen Feldgruppe mit Variablen kann auf einem beliebigen Datenabschnitt, Datentabellenabschnitte ausgenommen, basieren:
  • Basiselemente
  • Datenelemente
  • Datensätze (beliebiger Typ)
  • Stellvertreter
Die Feldgruppe selbst weist eine Identität auf, die nicht von den enthaltenen Elementen abhängt:
  • Sie können mithilfe des Feldgruppennamens (Syntax:Feldgruppenname.Funktionsname()) verschiedene Funktionen aufrufen, um die Anzahl der Elemente zur Laufzeit zu erhöhen oder zu verringern (siehe 'Dynamische Feldgruppenfunktionen').
  • Mit der feldgruppenspezifischen Eigenschaft maxSize wird die maximal zulässige Anzahl von Elementen in der Feldgruppe angegeben. Standardmäßig ist die Anzahl nicht begrenzt. Bei mehrdimensionalen Feldgruppen bezieht sich diese Eigenschaft nur auf die erste Dimension.
Sie müssen in Ihrer Deklaration keine Anzahl von Elementen angeben. Wenn Sie dies jedoch tun, gibt dieser Wert die anfängliche Anzahl der Elemente an. Schließen Sie bei mehrdimensionalen Feldgruppen die einzelnen Indizes jeweils in eckige Klammern ein:
multiDimensionArray INT[2][3];

Die folgenden Beispiele verdeutlichen die Syntax für die Deklaration einer dynamischen Feldgruppe:

  // Feldgruppe mit maximal 5 Elementen
  myNames CHAR(30)[] { maxSize=5 };

  // Feldgruppe mit maximal 6 Elementen 
  // und anfänglich 4 Elementen
  myDataItemArray myDataItem[4] { maxSize=6 };

  // Feldgruppe ohne Elemente, 
  // deren maximale Größe den höchstmöglichen Wert aufweist.
  myRecordArray ExampleRecord[];

  // Feldgruppe mit 3 Elementen, denen 
  // die Werte 1, 3 und 5 zugeordnet sind.
  position int[] = [1,3,5]; 

Für die Initialisierung der Elementanzahl können Sie ein ganzzahliges Literal verwenden. Variablen oder Konstanten sind in diesem Fall nicht zulässig.

Wie andere Referenzvariablen (siehe 'Referenzvariablen') können Sie auch Feldgruppenvariablen erst nach der Initialisierung verwenden.
myIntArray INT[];
myIntArray[2] = 13; // Führt zu einer Ausnahme des Typs 'NullValueException'.

myIntArray2 INT[3]
myIntArray2[2] = 13; // Dies ist zulässig.
Wenn Sie eine Feldgruppe mit Feldgruppen deklarieren, ist eine anfängliche Anzahl von Elementen in der ganz linken Dimension und in allen folgenden Dimensionen gültig, bis eine Dimension ohne anfängliche Anzahl folgt. Folgende Deklarationen sind gültig:
  // Gültig. maxsize gibt das Maximum 
  // für die erste Dimension an.
  myIntArray01 INT[3][];
  myIntArray02 INT[4][2][] {maxsize = 12};
  myIntArray03 INT[7][3][1];

  // Beim nächsten Beispiel gibt die Feldgruppenkonstante 
  // an, dass die übergeordnete Feldgruppe anfänglich über 3 Elemente verfügt.
  // Das erste Element der übergeordneten Feldgruppe ist 
  // eine Feldgruppe bestehend aus zwei Elementen mit den Werten 1 und 2.
  // Das zweite Element der übergeordneten Feldgruppe ist
  // eine Feldgruppe bestehend aus drei Elementen mit den Werten 3, 4 und 5.
  // Das dritte Element der übergeordneten Feldgruppe ist 
  // eine Feldgruppe bestehend aus zwei Elementen mit den Werten 6 und 7.
  myIntArray04 INT[][] = [[1,2],[3,4,5],[6,7]];
Die Syntax im folgenden Beispiel ist nicht zulässig, da die Feldgruppe myInt04 beispielsweise als Feldgruppe ohne Elemente deklariert wird, obwohl jedem einzelnen Element 3 Elemente zugeordnet sind:
  // NICHT gültig
  myInt04 INT[][3];
  myInt05 INT[5][][2];
Wenn Ihr Code eine Feldgruppe oder ein Feldgruppenelement referenziert, gelten folgende Regeln:
  • Sie können als Index einen numerischen Ausdruck verwenden, der in eine ganze Zahl aufgelöst wird. Ein Index kann auch einen Funktionsaufruf enthalten.
  • Wenn in Ihrem Code eine dynamische Feldgruppe ohne Angabe von Indizes referenziert wird, bezieht sich die Referenz auf die Feldgruppe als Ganzes.

Ein Speichermangel wird als nicht behebbarer Fehler angesehen und beendet das Programm.

Für die Initialisierung einer Feldgruppe können Sie einen Wertdefinitionsblock verwenden. Dazu folgende Beispiele:
myArray1 int[3] {1,2,3};  // Feldgruppe mit 3 Elementen mit den Werten 1, 2 und 3

Dies ist effizienter als eine Gleichsetzung der neuen Feldgruppe mit dem Feldgruppenliteral [1,2,3]. Beim Feldgruppenliteral muss von EGL zuerst das Feldgruppenliteral erstellt werden, bevor der Wert zu myArray1 zugeordnet wird. Bei Verwendung eines Wertdefinitionsblocks wird nur myArray1 erstellt.

Die folgende Deklaration schlägt jedoch fehl, da die anfängliche Feldgruppengröße mit null angegeben ist:
myArray2 int[] {1,2,3}; // Löst eine Ausnahme des Typs 'IndexOutOfBoundsException' aus.
Wenn Sie aus bestimmten Gründen eine Feldgruppe ohne Angabe einer anfänglichen Anzahl von Elementen erstellen müssen, die Feldgruppengröße jedoch nicht null sein darf (Sie möchten zu einem späteren Zeitpunkt Elemente hinzufügen), können Sie die folgende Syntax verwenden:
myArray3
int[] {};  // Feldgruppe mit Nulllänge, aber keine Null-Feldgruppe

Verwendung von dynamischen Feldgruppen als Parameter und Argumente

Eine dynamische Feldgruppe kann als Argument an eine EGL-Funktion übergeben werden. Der zugehörige Parameter muss als dynamische Feldgruppe desselben Typs wie das Argument definiert sein. Elemente müssen in Argument und Parameter dieselbe Länge und dieselbe Anzahl von Dezimalstellen (soweit vorhanden) aufweisen.

Eine an ein Programm oder eine Funktion übergebene Feldgruppe kann keine Elementanzahl angeben.

Das folgende Beispiel veranschaulicht eine Funktion, bei der eine dynamische Feldgruppe als Parameter verwendet wird:
  Function getAll (CustomerRecord myCustomers[])
   ;
  end

Zur Laufzeit entspricht die maximale Größe eines Parameters der für das entsprechende Argument deklarierten maximalen Größe. Von der aufgerufenen Funktion kann die Größe des Arguments verändert werden. Die Änderung wird im aufrufenden Code angewendet.

Feldgruppen mit Strukturfeldern

Sie deklarieren eine Feldgruppe mit Strukturfeldern, wenn Sie wie im folgenden Beispiel angeben, dass ein Feld in einem strukturierten Datensatz mehrmals vorkommt:
  Record ExampleStructuredRecord
    10 mySi CHAR(1)[3];
  end

Basiert eine Variable eines strukturierten Datensatzes namens myRecord auf dieser Definition, bezieht sich der Name myRecord.mySi auf eine eindimensionale Feldgruppe mit 3 Elementen, wobei es sich bei jedem Element um ein Zeichen handelt.

Verwendung von Feldgruppen mit Strukturfeldern

Eine vollständige Feldgruppe mit Strukturfeldern (z. B. myRecord.mySi) können Sie in den folgenden Kontexten referenzieren:
  • Als zweiter Operand eines Operators in. Der Operator testet, ob ein gegebener Wert in der Feldgruppe enthalten ist.
  • Als Parameter in der Funktion sysLib.size(). Die betreffende Funktion gibt die Anzahl der Elemente in der Feldgruppe zurück.

Ein Feldgruppenelement, bei dem es sich nicht um eine Feldgruppe handelt, stellt ein Feld wie alle anderen Felder auch dar. Sie können dieses Feld auf unterschiedliche Weise referenzieren, z. B. in einer Zuordnungsanweisung oder als Argument bei einem Funktionsaufruf.

Bei einem Elementindex kann es sich um einen beliebigen numerischen Ausdruck handeln, der in eine ganze Zahl aufgelöst wird. Der Ausdruck darf jedoch keinen Funktionsaufruf enthalten.

Eindimensionale Feldgruppen mit Strukturfeldern

Sie können auf ein Element einer eindimensionalen Feldgruppe wie z. B. myRecord.mySi verweisen, indem Sie den Namen der Feldgruppe gefolgt von einer in eckige Klammern gesetzten Indexnummer verwenden. Auf das zweite Element der Beispielfeldgruppe können Sie beispielsweise mit myStruct.mySi[2] verweisen. Als Index ist eine Zahl von 1 bis zur maximalen Anzahl von Elementen in der Feldgruppe zulässig. Liegt ein Index außerhalb dieses Bereichs, wird ein Laufzeitfehler ausgelöst.

Sie können den Namen einer Feldgruppe mit Strukturfeldern nicht in einem Kontext verwenden, indem ein Einzelwert benötigt wird, sofern Sie nicht einen Index angeben (mögliche Ausnahmen hierzu finden Sie unter der Überschrift 'Kompatibilität' in diesem Abschnitt).

Eine eindimensionale Feldgruppe kann wie die Feldgruppe im folgenden Beispiel unterstrukturiert sein:
  Record Record01
    10 name[3];
      20 firstOne CHAR(20);
      20 midOne CHAR(20);
      20 lastOne CHAR(20);
  end

Basiert ein Datensatz namens myRecord01 auf der oben angegebenen Datensatzdefinition, verweist der Name myRecord01.name auf eine eindimensionale Feldgruppe mit drei Elementen, die wiederum jeweils 60 Zeichen enthalten, und die Länge von myRecord01 beträgt 180.

Sie können auf die einzelnen Elemente in myRecord01.name verweisen, ohne die Unterstruktur zu referenzieren. myRecord01.name[2] verweist z. B. auf das zweite Element. Sie können auch auf eine Unterstruktur innerhalb eines Elements verweisen. Sofern die Regeln für die Eindeutigkeit von Elementen erfüllt sind, können Sie z. B. die letzten 20 Elemente des zweiten Elements auf eine der folgenden Weisen referenzieren:

  myRecord01.name.lastOne[2]
  myRecord01.lastOne[2]	
  lastOne[2]

Das letzte Beispiel ist nur gültig, wenn die Eigenschaft allowUnqualifiedItemReferences mit YES definiert ist.

Weitere Informationen zu den verschiedenen Arten von Referenzen finden Sie im Abschnitt zum Referenzieren von Variablen in EGL.

Feldgruppen mit mehrdimensionalen Strukturfeldern

Weist ein Strukturfeld mit mehreren Elementen eine untergeordnete Struktur auf und enthält das untergeordnete Strukturfeld ebenfalls mehrere Elemente, wird vom untergeordneten Strukturfeld eine Feldgruppe mit einer zusätzlichen Dimension deklariert (siehe 'Kompatibilität').

Als Beispiel dient an dieser Stelle ein weiterer Datensatzabschnitt:
  Record Record02
    10 siTop[3];
      20 siNext CHAR(20)[2];
  end
Basiert eine Datensatzvariable namens myRecord02 auf diesem Abschnitt, handelt es sich bei jedem Element der eindimensionalen Feldgruppe myRecord02.siTop selbst um eine eindimensionale Feldgruppe. Auf die zweite der drei untergeordneten eindimensionalen Feldgruppen können Sie beispielsweise mit myRecord02.siTop[2] verweisen. Mit dem Strukturfeld siNext wird eine zweidimensionale Feldgruppe deklariert und Sie können auf ein Element dieser Feldgruppe verweisen, indem Sie sich an einem der folgenden Syntaxbeispiele orientieren:
  // Zeile 1, Spalte 2.
  // Die nachfolgende Syntax wird dringend empfohlen,
  // da sie auch mit dynamischen Feldgruppen verwendet werden kann.
  myRecord02.siTop[1].siNext[2]

  // Die nachfolgende Syntax wird unterstützt,
  // eine Verwendung wird jedoch nicht empfohlen.
  myRecord02.siTop.siNext[1,2]

Bei der Frage, welche Speicherbereiche referenziert werden, ist es hilfreich zu wissen, wie Daten in einer mehrdimensionalen Feldgruppe gespeichert werden. Der als Beispiel aufgeführte Datensatz myRecord02 umfasst 120 Bytes. Der referenzierte Bereich ist in eine eindimensionale Feldgruppe mit drei Elementen von jeweils 40 Bytes unterteilt:

  siTop[1]     siTop[2]     siTop[3]

Die einzelnen Elemente der eindimensionalen Feldgruppe sind wiederum jeweils in eine Feldgruppe mit zwei Elementen von jeweils 20 Bytes in demselben Speicherbereich unterteilt:

  siNext[1,1] siNext[1,2] siNext[2,1] siNext[2,2] siNext[3,1] siNext[3,2]
Eine zweidimensionale Feldgruppe wird in einer zeilenweisen Anordnung gespeichert. Dies impliziert u. a., dass Sie, wenn Sie eine Feldgruppe in einer doppelten while-Schleife initialisieren, einen höheren Durchsatz erzielen, wenn die Spalten in der einen Zeile vor den Spalten in der nächsten Zeile verarbeitet werden. Zur Veranschaulichung folgendes Beispiel:
  // i, j, myTopIndex und myNextIndex sind Variablen. 
  // myRecord02 ist ein Datensatz und
  // sysLib.size() gibt die Anzahl der Elemente in einem Strukturfeld zurück.
  i = 1;
  j = 1;
  myTopIndex = sysLib.size(myRecord02.siTop);
  myNextIndex = sysLib.size(myRecord02.siTop.siNext);
  while (i <= myTopIndex)
    while (j <= myNextIndex)
      myRecord02.siTop.siNext[i,j] = "abc";
      j = j + 1;
    end
    i = i + 1;
  end

Für jede Dimension einer mehrdimensionalen Feldgruppe müssen Sie einen Wert angeben. Die Referenz myRecord02.siTop.siNext[1] ist beispielsweise nicht für eine zweidimensionale Feldgruppe zulässig.

Die folgende Deklaration ist ein Beispiel für eine Deklaration für eine dreidimensionale Feldgruppe:
  Record Record03
    10 siTop[3];
      20 siNext[2];
        30 siLast CHAR(20)[5];
  end
Das Einfügen von Feldgruppenindizes lässt sich anhand der folgenden Situation erläutern, bei der zunächst keine Indizes vorliegen:
  • Sie können eine Liste angeben, die mit dem Namen der Variablen beginnt und mit den Namen immer weiter untergeordneter Strukturfelder fortgesetzt wird. Die einzelnen Namen müssen dabei wie im folgenden Beispiel durch einen Punkt voneinander getrennt sein:
      myRecord03.siTop.siNext.siLast
  • Ist der Name des Feldes der untersten Ebene innerhalb der Variablen eindeutig, können Sie wie im folgenden Beispiel den Namen der Variablen gefolgt von einem Punkt und dem Namen des Felds der untersten Ebene angeben:
      myRecord03.siLast
  • Ist das Feld der untersten Ebene in einem Namespace eindeutig, können Sie wie im folgenden Beispiel auch nur das betreffende Feld angeben:
      siLast
Als nächstes sind die Regeln für das Anordnen von Feldgruppenindizes an dieser Stelle von Interesse:
  • Sie können einen Index wie im folgenden Beispiel auf jeder einzelnen Ebene angeben, auf der eines von mehreren Elementen gültig ist:
      myRecord03.siTop[3].siNext[2].siLast[5]
  • Sie können eine Reihe von Indizes wie im folgenden Beispiel auf jeder beliebigen Ebene angeben, auf der eines von mehreren Elementen gültig ist:
      myRecord03.siTop.siNext[3,2].siLast[5]
  • Sie können eine Reihe von Indizes wie im folgenden Beispiel auf jeder beliebigen Ebene angeben, die sich auf derselben Ebene befindet oder einer Ebene untergeordnet ist, auf der eines von mehreren Elementen gültig ist:
      myRecord03.siTop.siNext.siLast[3,2,5]
  • Ein Fehler tritt auf, wenn Sie mehr Indizes zuordnen als auf einer bestimmten Ebene adäquat. Dazu folgendes Beispiel:
      // NICHT gültig
      myRecord03.siTop[3,2,5].siNext.siLast
  • Sie können einen Index mit einer eckigen Klammer von den anderen trennen, eine Reihe von durch Kommata voneinander getrennten Indizes angeben oder diese beiden Optionen miteinander kombinieren. Bei den folgenden Beispielen handelt es sich um eine gültige Syntax:
      myRecord03.siTop.siNext.siLast[3,2,5]
      myRecord03.siTop.siNext.siLast[3,2][5]
      myRecord03.siTop.siNext.siLast[3][2,5]
      myRecord03.siTop.siNext.siLast[3][2][5]

Kompatibilität

Tabelle 2. Hinweise zur Kompatibilität für Feldgruppen
Plattform Problem
COBOL-Generierung Mehrdimensionale Feldgruppen werden nicht für dynamische Feldgruppen unterstützt.
JavaScript-Generierung Die folgenden Typen werden unterstützt: ANY, BIGINT, BIN (nur ohne Dezimalstellen), Boolean, DataItem, DATE, DECIMAL, Delegate, Dictionary, FLOAT, INT, NUM, NUMBER, SMALLFLOAT, SMALLINT, STRING (nur ohne Größenbegrenzung) , TIME, TIMESTAMP, NUM, MONEY, Serviceabschnitte, Schnittstellenabschnitte, externe Typen (Stereotyp JavaScript), Feldgruppen mit unterstützten Typen, nicht strukturierte Basisdatensätze sowie Ausnahmedatensätze und SQL-Datensatzabschnitte.

Die folgenden Typen werden nicht unterstützt: ArrayDictionary, BIN (mit Dezimalstellen), BLOB, CHAR, CLOB, DBCHAR, HEX, INTERVAL, MBCHAR, NUMC, STRING (mit Größenbegrenzung), PACF, UNICODE und strukturierte Datensatzabschnitte.

VisualAge Generator-Kompatibilitätsmodus Wenn Sie den Namen einer Feldgruppe mit Strukturfeldern in einem Kontext ohne Index verwenden, in dem ein Einzelwert benötigt wird, geht EGL davon aus, dass Sie sich auf das erste Element der Feldgruppe beziehen.

Feedback