オープン配列パラメータ

オープン配列パラメータとは、異なるサイズの配列を同じ手続き、又は関数に渡せることを言います オープン配列パラメータの宣言は以下のようになります。

procedure MyProc(Arr: array of Integer);
begin
  ..........
end;

このように、パラメータに array of 型 としてやることでオープン配列パラメータにすることが出来ます。早速、例を見てみましょう。フォームには ListBox が2つ、Button が1つ貼り付けてあります。

procedure MyProc(Arr: array of Integer);
var
  i: Integer;
begin
  for i := Low(Arr) to High(Arr) do
  begin
    Arr[i] := 10; // 受け取った要素を全て10にする
    Form1.ListBox2.Items.Add('Array[ ' + IntToStr(i) + ' ] = ' +
      IntToStr(Arr[i]));
  end;
  
  Form1.ListBox2.Items.Add('');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  Arr1: array[0..3] of Integer;
  Arr2: array[0..5] of Integer;
begin
  for i := Low(Arr1) to High(Arr1) do
  begin
    Arr1[i] := i; 
    ListBox1.Items.Add('Arr1[ ' + IntToStr(i) + ' ] = ' +
      IntToStr(Arr1[i]));
  end;
  
  ListBox1.Items.Add(''); // 一行間隔をあけます

  for i := Low(Arr2) to High(Arr2) do
  begin
    Arr2[i] := 100 + i;
    ListBox1.Items.Add('Arr2[ ' + IntToStr(i) + ' ] = ' +
      IntToStr(Arr2[i]));
  end;
 
  // 手続きMyProcに、それぞれの配列を渡す
  MyProc(Arr1);
  MyProc(Arr2);
end;

ここでは、受け取った配列の要素を全て10に変更しています。このように、サイズの異なる配列を1つの手続きに渡すことが出来ます。また、配列のサイズを知る為に Low()、High() を使用している点にも注目してください。ただ、オープン配列パラメータの場合、添え字は常に0から始まるという規則がありますので、その点は注意が必要です。

また Slice 関数を使うことによって、渡す配列の要素数を予め決めることが出来ます。

procedure MyProc(Arr: array of Integer);
var
  i: Integer;
begin
  for i := Low(Arr) to High(Arr) do
  begin
    Arr[i] := 10;
    Form1.ListBox2.Items.Add('Array[ ' + IntToStr(i) + ' ] = ' +
      IntToStr(Arr[i]));
  end;
 
  Form1.ListBox2.Items.Add('');
end;
  
procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
  Arr1: array[0..3] of Integer;
  Arr2: array[0..5] of Integer;
begin
  for i := Low(Arr1) to High(Arr1) do
  begin
    Arr1[i] := i;
    ListBox1.Items.Add('Arr1[ ' + IntToStr(i) + ' ] = ' +
      IntToStr(Arr1[i]));
  end;
  
  ListBox1.Items.Add('');

  for i := Low(Arr2) to High(Arr2) do
  begin
    Arr2[i] := 100 + i;
    ListBox1.items.Add('Arr2[ ' + IntToStr(i) + ' ] = ' +
      IntToStr(Arr2[i]));
  end;
  
  MyProc(Arr1);
  MyProc(Slice(Arr2, 3)); // (1)
end;

(1)のように Slice 関数を使用した場合、Arr2 は配列の先頭から、つまり Arr2[0] から Arr2[1]、Arr2[2] の3つが手続き MyProc に渡されることになります。それでは、もう一つ例を見てみましょう。

function Sum(A: array of Integer): Integer;
var
  i: Integer;
begin
  Result := 0;
  
  for i := Low(A) to High(A) do
    Inc(Result, A[i]);
end;
  
procedure TForm1.Button1Click(Sender: TObject);
var
  Arr: array[0..5] of Integer;
  i: Integer;
begin
  Arr[0] := 1;
  Arr[1] := 2;
  Arr[2] := 3;
  Arr[3] := 4;
  Arr[4] := 5;
  Arr[5] := 6;
  
  i := Sum(Arr);
  ShowMessage('合計 ' + IntToStr(i));
end;

オープン配列パラメータは動的配列の宣言と似ていますが、動的配列の宣言ではないので注意してください。つまりパラメータ(引数)で「array of ..」となっていたら、必ずオープン配列パラメータです これは、動的配列を渡せないということでは、ありません。以下のように動的配列も渡せます。

function Sum(A1, A2: array of Integer): Integer;
var
  i, x1, x2: Integer;
begin
  x1 := 0;
  x2 := 0;
  
  for i := Low(A1) to High(A1) do
    Inc(x1, A1[i]);
  
  for i := Low(A2) to High(A2) do
    Inc(x2, A2[i]);
  
  Result := x1 + x2;
end;
  
procedure TForm1.Button1Click(Sender: TObject);
var
  Arr1: array[0..5] of Integer;
  Arr2: array of Integer;
  i: Integer;
begin
  Arr1[0] := 1;
  Arr1[1] := 2;
  Arr1[2] := 3;
  Arr1[3] := 4;
  Arr1[4] := 5;
  Arr1[5] := 6;
  
  SetLength(Arr2, 3);
  Arr2[0] := 1;
  Arr2[1] := 10;
  Arr2[2] := 100;
 
  i := Sum(Arr1, Arr2);
  ShowMessage('合計 ' + IntToStr(i));
end;

では、何が出来ないのかというと渡された動的配列のサイズの変更が出来ないのです。

オープン配列コンストラクタ
オープン配列コンストラクタは、手続きや関数に値を渡す際、直接配列を作成して渡すことを言います。また、渡すことの出来る手続きや関数のパラメータは、オープン配列パラメータでなければなりません。
function Sum(Arr: array of Integer): Integer;
var
  i: Integer;
begin
  Result := 0;
 
  for i := Low(Arr) to High(Arr) do
    Result := Result + Arr[i];
  
  i := SizeOf(Arr) div SizeOf(Integer);
  ShowMessage('要素数は ' + IntToStr(i));
end;
  
procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  // 直接配列を作成
  i := Sum([10, 20, 20, 30]);
  ShowMessage('合計 ' + IntToStr(i));
  
  i := Sum([1, 2, 3]);
  ShowMessage('合計 ' + IntToStr(i));
 
end;

このように、手続き又は関数の呼び出し時に直接配列を作成して渡すことが出来ます。

関数や手続きのパラメータに動的配列を宣言する方法は別にあります。その場合は、新しい型を自分で宣言してから使わなければなりません。下の例を参考にして下さい。

type
  // 独自の型を定義
  TDynamicArr = array of Integer;

  ..................................
  
procedure Sum(var A: TDynamicArr);
begin
  SetLength(A, 20);
end;
  
procedure TForm1.Button1Click(Sender: TObject);
var
  Arr: TDynamicArr;
  i: Integer;
begin
  SetLength(Arr, 10);
  i := Length(Arr);
  ShowMessage('要素数は ' + IntToStr(i));
  
  Sum(Arr);
  i := Length(Arr);
  ShowMessage('要素数は ' + IntToStr(i));
end;

このようにした場合、サイズの変更が可能になります。


up next
Last update 2002/3/3