配列

EGL では、以下の種類の配列がサポートされます。

いずれの場合でも、サポートされる次元の最大数は 7 です。

動的配列

プリミティブ変数の配列またはレコード (BasicRecord 型、DLISegment 型、または SQLRecord 型) を宣言すると、その配列は配列内のエレメントに依存しない独自性を持ちます。
  • その配列に固有の関数セットがあり、それらの関数を使用して、エレメントの数を実行時に増減できます。
  • 配列固有プロパティー maxSize は、その配列内で有効なエレメントの数を示します。 デフォルト値は無制限で、エレメントの数はターゲット環境の要件によってのみ制限を受けます。

宣言の中でエレメントの数を指定する必要はありませんが、宣言した場合は、その数が初期のエレメント数を示します。 また、宣言の中で、一連の配列定数をリストすることによって初期のエレメント数を指定することもできます。ただし、これはプリミティブ変数でのみ可能であり、レコードでは不可能です。

動的配列を宣言するための構文を以下の例で示します。

  // エレメントの数が 5 つ以下の配列
  myDataItem01 CHAR(30)[] { maxSize=5 };

  // エレメントの数が 6 つ以下の配列で、
  // 初期のエレメントは 4 つ
  myDataItem02 myDataItemPart[4] { maxSize=6 };

  // エレメントなしの配列
  // ただし、最大サイズは可能な限り最大となります。
  myRecord ExampleRecordPart[];

  // 3 つのエレメントの配列で、エレメントには
  // 値 1、3、5 が代入されます。
  position int[] = [1,3,5]; 

リテラル整数を使用してエレメントの数を初期設定できますが、変数と定数は、どちらも無効です。

配列の配列を宣言する場合、初期のエレメント数が有効となるのは、指定された最も左側の次元と、それ以降、初期数が指定されない次元までの各次元です。 以下のような宣言が有効です。
  // 有効。maxsize で最初の次元の
  // 最大値を指定
  myInt01 INT[3][];
  myInt02 INT[4][2][] {maxsize = 12};
  myInt03 INT[7][3][1];

  // 次の例では、配列定数により、外側の配列が
  // 初期に 3 つのエレメントを持つことを示しています。
  // 外側の配列の第 1 エレメントは、2 つの
  // エレメント (値は 1 と 2) からなる配列です。
  // 外側の配列の第 2 エレメントは、3 つのエレメント
  // (値は 3、4、5) からなる配列です。
  // 外側の配列の第 3 エレメントは、2 つの
  // エレメント (値は 6 と 7) からなる配列です。
  myInt04 INT[][] = [[1,2],[3,4,5],[6,7]];
次の例に示す構文は無効です。その理由は、(例えば) 配列 myInt04 がエレメントなしの配列として宣言されているにもかかわらず、それぞれのエレメントに 3 つのエレメントが代入されているからです。
  // 無効
  myInt04 INT[][3];
  myInt05 INT[5][][2];

プログラムまたは関数のパラメーターとして指定された配列が、エレメントの数を指定することはできません。

ご使用のコードで、配列または配列エレメントを参照するときは、次の規則が適用されます。
  • エレメントの添え字として、整数に解決される任意の数式を使用できますが、 式に、関数呼び出しを組み込むことはできません。
  • コードで動的配列を参照するが、添え字を指定しない場合は、配列全体が参照されます。

メモリー不足状態は破局的エラーとして扱われ、プログラムが終了します。

動的配列関数

動的配列ごとに、一連の関数および読み取り専用変数が使用可能です。 次の例では、配列は series と呼ばれます。
  series.reSize(100);
配列の名前に一連の大括弧を組み込み、それぞれの大括弧に整数を入れることもできます。 以下に例を示します。
  series INT[][];

  // 配列の配列である series の
  // 第 2 エレメントのサイズを変更
series[2].reSize(100);

以下のセクションでは、arrayName を配列名で置き換えます。 また、名前はパッケージ名かライブラリー名、またはその両方で修飾できることに注意してください。

appendAll()

  arrayName.appendAll(appendArray  Array in)
この関数は以下のことを実行します。
  • appendArray によって参照される配列のコピーを追加して、arrayName によって参照される配列に付加する
  • 追加したエレメントの数だけ配列サイズを増分する
  • 付加したエレメントごとに適切な索引値を割り当てる

appendArray のエレメントの型は、arrayName のエレメントの型と同じでなければなりません。

appendElement()

  arrayName.appendElement(content ArrayElement in)

この関数は、指定された配列の末尾にエレメントを置き、サイズを 1 ずつ増分します。 content は、適切な型の変数に置き換えることができます。 または、操作中に作成されたエレメントに割り当てられるリテラルを指定できます。 このプロセスではデータがコピーされるため、 ある変数を割り当てても、その変数を比較または他の目的に使用できます。

リテラルを割り当てるための規則は、『代入』で説明したとおりです。

getMaxSize()

  arrayName.getMaxSize ( ) returns (INT)

この関数は、その配列内で許容されるエレメントの最大値を示す整数を戻します。

getSize()

  arrayName.getSize ( ) returns (INT)

この関数は、その配列内のエレメント数を示す整数を戻します。 動的配列を処理するときは、この関数を SysLib.size の代わりに使用することをお勧めします。

arrayName.getSize に相当する機能を持つ別の関数があります。
SysLib.size( ) returns (INT)

しかし、動的配列を処理するときは、arrayName.getSize ( ) を使用することをお勧めします。

insertElement()

  arrayName.insertElement (content ArrayElement in, index INT in)
この関数は以下のことを実行します。
  • あるエレメントを、現在配列内の指定されたロケーションにあるエレメントの前に置く。
  • 配列サイズを 1 つずつを増分する
  • 挿入されたエレメントの後ろにある各エレメントの指標を増分する

content は新しい内容 (配列の適切な型の定数または変数) で、 index は新規エレメントのロケーションを示す整数リテラルまたは数値変数です。

index が配列内のエレメント数より大きい場合は、 関数は新規エレメントを配列の末尾に作成し、配列サイズを 1 つずつ増分します。

removeAll()

  arrayName.removeAll( )

この関数は、メモリーから配列のエレメントを除去します。配列を使用することはできますが、配列のサイズはゼロです。

removeElement()

  arrayName.removeElement(index INT in)

この関数は、指定されたロケーションのエレメントを除去し、 配列サイズを 1 つずつ減分し、除去されたエレメントの後ろにある各エレメントの指標を減分します。

index は、 除去するエレメントのロケーションを示す整数リテラルまたは数値変数です。

resize()

  arrayName.resize(size INT in)

この関数は、配列の現行サイズを size (整数リテラル、定数、変数のいずれか) で指定されたサイズまで増減します。 size の値が、その配列に許容される最大サイズより大きい場合は、実行単位が終了します。

reSizeAll()

  arrayName.reSizeAll(sizes INT[
] in)

この関数は、多次元配列のすべての次元を増減します。 パラメーター sizes は整数の配列で、連続したそれぞれのエレメントが、逐次 1 つの次元のサイズを指定します。 サイズ変更された次元数が arrayName 内の次元数より大きい場合、または sizes 内のエレメントの値が arrayName の相応の次元内で許容される最大サイズより大きい場合は、実行単位が終了します。

setMaxSize()

  arrayName.setMaxSize (size INT in)

この関数は、その配列内で許容されるエレメントの最大値を設定します。 この最大サイズをその配列の現行サイズより小さく設定した場合は、実行単位が終了します。

setMaxSizes()

  arrayName.setMaxSizes(sizes INT[
] in)

この関数は、多次元配列のすべての次元を設定します。 パラメーター sizes は整数の配列で、連続したそれぞれのエレメントが、逐次 1 つの次元の最大サイズを指定します。 指定された次元数が arrayName 内の次元数より大きい場合、または sizes 内のエレメントの値が arrayName の相応の次元内で現行エレメント数より小さい場合は、実行単位が終了します。

引数およびパラメーターとしての動的配列の使用

動的配列は、EGL 関数に引数として渡すことができます。関連するパラメーターは、 引数と同じ型の動的配列として定義する必要があり、データ項目については、 型の長さおよび小数点以下の桁数は同じでなければなりません (存在する場合)。

次の型の動的配列は、プログラムに渡すことができます。
  • プリミティブ型
  • BasicRecord 型、DLISegment 型、または SQLRecord 型のレコード
動的配列をパラメーターとして使用する関数の例は、以下のとおりです。
  Function getAll (employees Employee[])
   ;
  end

実行時に、パラメーターの最大サイズは、対応する引数に宣言された最大サイズになります。呼び出された関数は配列のサイズを変更することができ、その変更は呼び出し側コードで有効になります。

SQL 処理と動的配列

EGL では、動的配列を使用してリレーショナル・データベースの行にアクセスできます。 複数行を読み取る方法の詳細については、『get』を参照してください。複数行を追加する方法の詳細については、『add』を参照してください。

構造体フィールド配列

構造体フィールド配列を宣言するのは、次の例に示すように、固定構造体内のフィールドに複数の出現箇所があるときです。
  Record ExampleFixedRecordPart
    10 mySi CHAR(1)[3];
  end

myRecord という固定レコードが、このパーツに基づいている場合、シンボル myRecord.mySi は、3 つのエレメント (それぞれが 1 文字) からなる 1 次元配列を参照します。

構造体フィールド配列の使用法

以下のようなコンテキストでは、構造体フィールドの配列全体 (例えば、myRecord.mySi) を参照できます。
  • in 演算子によって使用される第 2 オペランドとして。この演算子は、指定された値が配列に含まれているかどうかをテストします。
  • 関数 sysLib.size のパラメーターとして。 この関数は、構造体フィールドの occurs 値を戻します。

それ自体が配列ではない配列エレメントは、他のエレメントと同様に 1 つ のフィールドであり、さまざまな方法で参照できます。 例えば、代入文の中で参照したり、関数呼び出しの引数として参照したりできます。

エレメントの添え字として、整数に解決される任意の数式を使用できますが、 式に、関数呼び出しを組み込むことはできません。

1 次元構造体フィールド配列

myRecord.mySi のような 1 次元配列のエレメントを参照するときは、配列の名前を指定し、その後ろに大括弧で囲んだ添え字を指定します。添え字には、整数か、整数へと解決されるフィールドを指定します。例えば、myStruct.mySi[2] のようにすると、例に示した配列の 2 番目のエレメントを参照できます。 添え字は、1 から構造体フィールドの occurs 値までの間で変化します。 この範囲の外で添え字が指定されると、ランタイム・エラーが発生します。

フィールドを必要とするコンテキスト内で構造体フィールド配列の名前を使用し、大括弧で囲った添え字を指定しなかった場合、EGL では、VisualAge® Generator との互換性モードであるときに限り、配列の最初のエレメントを参照していると見なされます。 各エレメントを明示的に識別することをお勧めします。 VisualAge Generator との互換性モードでない場合は、各エレメントを明示的に識別する必要があります。

次の例は、1 次元配列内のエレメントを参照する方法を示しています。 これらの例では、valueOne が 1 に解決され、valueTwo が 2 に解決されます。
  // 以下は、3 つのうち最初のエレメントを参照します
  myRecord.mySi[valueOne]

  // お勧めしません。これは
  // VisualAge Generator との互換性が
  // compatibility is in effect:
  myRecord.mySi                                    

  // 以下は、2 つ目のエレメントを参照します
  myRecord.mySi[valueTwo]
次の例に示すとおり、1 次元配列は副構造を持つことができます。
  record myRecord01Part
    10 name[3];
      20 firstOne CHAR(20);
      20 midOne CHAR(20);
      20 lastOne CHAR(20);
  end

myRecord01 というレコードが前のパーツに基づいている場合、 シンボル myRecord01.name は、それぞれが 60 文字の長さを持つ 3 つのエレメントの 1 次元配列を参照し、myRecord01 の長さは 180 になります。

副構造を参照しなくても、myRecord01.name 内の各エレメントを参照することは可能です。 例えば、myRecord01.name[2] は 2 番目のエレメントを参照します。 また、エレメント内の副構造を参照することもできます。例えば、固有性の規則が満たされている場合、以下のいずれかの方法で、2 番目のエレメントの最後の 20 文字を参照できます。

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

最後の 2 つは、生成可能パーツ・プロパティー allowUnqualifiedItemReferencesyes に設定されている場合にのみ有効です。

各種の参照については、『変数および定数の参照』を参照してください。

多次元構造体フィールド配列

1 より大きい occurs 値を持つ構造体項目に副構造があり、従属の構造体項目で occurs 値が 1 より大きい場合、その従属の構造体項目は、追加の次元を持つ配列を宣言します。

別のレコード・パーツについて考えて見ましょう。
  record myRecord02Part
    10 siTop[3];
      20 siNext CHAR(20)[2];
  end
myRecord02 というレコードがそのパーツに基づいている場合、1 次元配列 myRecord02.siTop の各エレメントは、 それ自体が 1 次元配列になっています。例えば、3 つの従属 1 次元配列の 2 番目は myRecord02.siTop[2] として参照できます。構造体項目 siNext は 2 次元配列を宣言します。この配列のエレメントは、以下のいずれかの構文によって参照できます。
  // 行 1、列 2 とします。
  // 次の構文を強くお勧めします。
  // なぜなら、動的配列に対しても機能するからです。
  myRecord02.siTop[1].siNext[2]

  // 次の構文は、VisualAge Generator との
  // 互換性のためにサポートされています。
myRecord02.siTop.siNext[1,2]

参照されるメモリーの領域を明確にするため、多次元配列ではどのようにデータが保管されるのかを考えましょう。 現在の例では、myRecord02 は 120 バイトです。参照される領域は、それぞれが 40 バイトの長さを持つ、3 つのエレメントの 1 次元配列に分けられます。

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

さらに、この 1 次元配列の各エレメントは、同じメモリーの領域の中で、それぞれが 20 バイトの長さを持つ 2 つのエレメントの配列に分けることができます。

  siNext[1,1] siNext[1,2] siNext[2,1] siNext[2,2] siNext[3,1] siNext[3,2]
2 次元配列は、行が大きい順に保管されます。 これには、配列をループで 2 重に初期設定するとき、1 つの行ごとに列を処理してゆくことによってパフォーマンスを高める意味があります。
  // i、j、myTopOccurs、および myNextOccurs は、データ項目です。
  // myRecord02 はレコードです。
  // sysLib.size() は、構造体項目の occurs 値を戻します。
    i = 1;
    j = 1;
  myTopOccurs = sysLib.size(myRecord02.siTop);
  myNextOccurs = sysLib.size(myRecord02.siTop.siNext);
    while (i <= myTopOccurs)
    while (j <= myNextOccurs)
      myRecord02.siTop.siNext[i,j] = "abc";
      j = j + 1;
    end
    i = i + 1;
  end

多次元配列の各次元に応じた値を指定する必要があります。 例えば、myRecord02.siTop.siNext[1] という参照は、2 次元配列では無効です。

3 次元配列の宣言の例を以下に示します。
  record myRecord03Part
    10 siTop[3];
      20 siNext[2];
        30 siLast CHAR(20)[5];
  end
myRecord03 というレコードがそのパーツに基づいており、 固有性の規則が満たされている場合は、以下のいずれかの方法で、配列の最後のエレメントを参照できます。
  // 推奨されているように、それぞれのレベルを示し、
  // 各レベルごとに添え字を指定します。
myRecord03.siTop[3].siNext[2].siLast[5]

  // それぞれのレベルを示し、下位レベルで添え字を指定する
  myRecord03.siTop.siNext[3,2].siLast[5]
  myRecord03.siTop.siNext[3][2].siLast[5]

  // それぞれのレベルを示し、最下位レベルで添え字を指定する
  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]

  // コンテナーと最後のレベルを添え字付きで示す
  myRecord03.siLast[3,2,5]
  myRecord03.siLast[3,2][5]
  myRecord03.siLast[3][2,5]
  myRecord03.siLast[3][2][5]

  // 最後のレベルのみを添え字付きで示す
  siLast[3,2,5]  siLast[3,2][5]
  siLast[3][2,5]
  siLast[3][2][5]

前の例で示したように、多次元配列のエレメントは、さまざまな方法で大括弧に入れた一連の添え字を追加することによって参照します。 いずれの場合でも、最初の添え字は第 1 の次元を参照し、2 番目の添え字は第 2 の次元を参照し、その後も同様です。 各添え字の値は、1 から関連する構造体項目の occurs 値までの間で変化します。 添え字がこの範囲の外の数値に解決されると、ランタイム・エラーが発生します。

最初に、添え字が組み込まれなかった状態を考慮してください。
  • 変数名を先頭に置いて、段階的に従属する構造体項目の名前をピリオドで区切ってリストしていったものを指定します。例えば、
      myRecord03.siTop.siNext.siLast
  • 変数名の直後にピリオドを付け、その後に、求める最下位レベル項目の名前を付けて指定できます。次に例を示します。
      myRecord03.siLast
  • 求める最下位レベル項目が所定の名前空間内で固有な場合は、次の例のように、その項目だけを指定できます。
      siLast
次に、配列添え字を配置するための規則を考慮します。
  • 複数のエレメントのいずれかが有効な場合は、次の例のように、それぞれのレベルごとに添え字を指定できます。
      myRecord03.siTop[3].siNext[2].siLast[5]
  • 複数のエレメントの 1 つが有効なレベルでは、次の例のように、一連の添え字を指定できます。
      myRecord03.siTop.siNext[3,2].siLast[5]
  • 複数のエレメントの 1 つが有効なレベル、またはそれに従属するレベルでは、次の例のように、一連の添え字を指定できます。
      myRecord03.siTop.siNext.siLast[3,2,5]
  • 所定のレベルで適切な添え字の数を超えて添え字を代入すると、エラーが発生します。 次に例を示します。
      // 無効
      myRecord03.siTop[3,2,5].siNext.siLast
  • 添え字を個々に大括弧に入れて分離するか、一連の添え字を表示するか、1 つずつコンマで区切ることができ、あるいは、2 つの使用法を結合してもかまいません。 以下の例は有効です。
      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]
フィードバック
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.