言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

Pascal辞典

  1. トップページ
  2. Pascal辞典
  3. オープン配列パラメータ(array of)

オープン配列パラメータ(array of)

『Pascal』のオープン配列パラメータは、手続き・関数の引数に『array of 型名』と宣言することで、任意のサイズの配列を受け取れるようにする仕組みです。呼び出し元が渡した配列の長さを『High(引数名)』で取得でき、インデックスは常に『0』から始まります。さらに Free Pascal の『array of const』を使うと、異なる型を混在させた可変長引数を受け取ることもできます。

構文

{ -----------------------------------------------
  オープン配列パラメータ(array of 型名)
  呼び出し元の配列サイズを問いません
  ----------------------------------------------- }

procedure 手続き名(arr : array of Integer);
var
  i : Integer;
begin
  { インデックスは 0 から High(arr) まで }
  for i := 0 to High(arr) do begin
    WriteLn(arr[i]);
  end;
end;

{ -----------------------------------------------
  const / var 修飾子との組み合わせ
  const を付けると読み取り専用になります
  ----------------------------------------------- }

procedure 手続き名(const arr : array of String);
begin
  { arr[0] := 'x'; }  { コンパイルエラーになります }
  WriteLn(arr[0]);
end;

{ -----------------------------------------------
  array of const — 異なる型を混在させた可変長引数
  各要素は TVarRec レコードとして渡されます
  ----------------------------------------------- }

procedure 手続き名(args : array of const);
var
  i : Integer;
begin
  for i := 0 to High(args) do begin
    case args[i].VType of
      vtInteger : WriteLn('Integer: ', args[i].VInteger);
      vtString  : WriteLn('String : ', args[i].VString^);
      vtBoolean : WriteLn('Boolean: ', args[i].VBoolean);
    end;
  end;
end;

{ -----------------------------------------------
  呼び出し例
  ----------------------------------------------- }

var
  scores : array[1..3] of Integer;

begin
  scores[1] := 90;
  scores[2] := 85;
  scores[3] := 92;

  手続き名(scores);        { 固定長配列を渡せます }
  手続き名([10, 20, 30]);  { 配列コンストラクタでも渡せます }

  { array of const の呼び出し }
  手続き名(['Itadori', 185, True]);
end;

構文一覧

構文 / 識別子概要
procedure P(arr : array of T);オープン配列パラメータです。任意のサイズの配列を受け取れます。インデックスは常に『0』から始まります。
procedure P(const arr : array of T);読み取り専用のオープン配列です。手続き・関数内で要素を書き換えようとするとコンパイルエラーになります。
High(arr)オープン配列の最大インデックス(要素数 - 1)を返します。要素数が 0 のときは『-1』を返します。
Low(arr)オープン配列の最小インデックスを返します。オープン配列では常に『0』です。
Length(arr)オープン配列の要素数を返します。『High(arr) + 1』と等価です。
[値1, 値2, ...]配列コンストラクタです。オープン配列引数に直接リテラルを並べて渡せます。
procedure P(args : array of const);型混在の可変長引数です。各要素は『TVarRec』型として渡されます。『WriteLn』と同様の引数渡し方が実現できます。
TVarRec.VType要素の型を示す定数です。『vtInteger』、『vtString』、『vtBoolean』、『vtChar』、『vtAnsiString』などがあります。
TVarRec.VInteger『VType = vtInteger』のとき、整数値を保持するフィールドです。
TVarRec.VString^『VType = vtString』のとき、ショート文字列へのポインタです。『^』でデリファレンスして文字列を取り出します。
TVarRec.VAnsiString『VType = vtAnsiString』のとき、AnsiString(通常の『String』)へのポインタです。『AnsiString(args[i].VAnsiString)』でキャストして使います。

サンプルコード

jjk_open_array.pas
{ jjk_open_array.pas — Pascal のオープン配列と array of const を確認するサンプルです }
{ 呪術廻戦のキャラクターを使って }
{ オープン配列パラメータと可変長引数の動作を確認します }
{
  コンパイルと実行:
    fpc jjk_open_array.pas && ./jjk_open_array
}

{$mode objfpc}
program jjk_open_array;

{ -----------------------------------------------
  手続き①: オープン配列パラメータ(array of Integer)
  呪術師の呪力値リストを受け取って合計と平均を計算します
  配列のサイズは問いません
  ----------------------------------------------- }
procedure PrintCurseEnergyStats(const name : String;
                                const energies : array of Integer);
var
  i     : Integer;
  total : Integer;
begin
  total := 0;
  WriteLn('--- ', name, ' の呪力値リスト ---');
  WriteLn('  要素数: ', Length(energies));

  for i := 0 to High(energies) do begin
    WriteLn('  [', i, '] ', energies[i]);
    total := total + energies[i];
  end;

  if Length(energies) > 0 then begin
    WriteLn('  合計  : ', total);
    WriteLn('  平均  : ', total div Length(energies));
  end;
  WriteLn('');
end;

{ -----------------------------------------------
  手続き②: オープン配列パラメータ(array of String)
  術式名のリストを受け取って番号付きで表示します
  ----------------------------------------------- }
procedure ListTechniques(const sorcerer : String;
                         const techniques : array of String);
var
  i : Integer;
begin
  WriteLn('--- ', sorcerer, ' の術式 ---');
  for i := 0 to High(techniques) do begin
    WriteLn('  ', i + 1, '. ', techniques[i]);
  end;
  WriteLn('');
end;

{ -----------------------------------------------
  手続き③: 配列を受け取って最大値のインデックスを返します
  var 修飾子で最大値とそのインデックスを呼び出し元に返します
  ----------------------------------------------- }
procedure FindMaxEnergy(const energies : array of Integer;
                        var max_val    : Integer;
                        var max_idx    : Integer);
var
  i : Integer;
begin
  max_val := energies[0];
  max_idx := 0;
  for i := 1 to High(energies) do begin
    if energies[i] > max_val then begin
      max_val := energies[i];
      max_idx := i;
    end;
  end;
end;

{ -----------------------------------------------
  手続き④: array of const — 型混在の可変長引数
  キャラクタープロフィールを任意の型の組み合わせで受け取ります
  TVarRec.VType で型を判定して表示します
  ----------------------------------------------- }
procedure PrintProfile(args : array of const);
var
  i : Integer;
begin
  for i := 0 to High(args) do begin
    case args[i].VType of
      vtInteger  :
        WriteLn('  [Integer ] ', args[i].VInteger);
      vtBoolean  :
        WriteLn('  [Boolean ] ', args[i].VBoolean);
      vtString   :
        { vtString は ShortString へのポインタです。^ でデリファレンスします }
        WriteLn('  [String  ] ', args[i].VString^);
      vtAnsiString :
        { vtAnsiString は AnsiString へのポインタです。キャストして使います }
        WriteLn('  [AnsiStr ] ',
                AnsiString(args[i].VAnsiString));
      vtChar     :
        WriteLn('  [Char    ] ', args[i].VChar);
    else
      WriteLn('  [Other   ] VType=', args[i].VType);
    end;
  end;
end;

{ -----------------------------------------------
  グローバル変数
  ----------------------------------------------- }
var
  { 虎杖悠仁の呪力値(測定回ごとに変わります) }
  itadori_energies : array[1..4] of Integer;

  { 伏黒恵の術式名 }
  fushiguro_techniques : array[1..3] of String;

  { 釘崎野薔薇の呪力値 }
  kugisaki_energies : array[1..3] of Integer;

  best_val : Integer;  { 最大呪力値 }
  best_idx : Integer;  { 最大呪力値のインデックス }

begin
  WriteLn('===== 呪術廻戦 オープン配列サンプル =====');
  WriteLn('');

  { -----------------------------------------------
    固定長配列をオープン配列パラメータに渡します
    虎杖悠仁の呪力値リストを設定します
    ----------------------------------------------- }
  itadori_energies[1] := 920;
  itadori_energies[2] := 980;
  itadori_energies[3] := 1050;
  itadori_energies[4] := 1100;

  PrintCurseEnergyStats('Yuji Itadori(虎杖悠仁)', itadori_energies);

  { -----------------------------------------------
    釘崎野薔薇の呪力値を配列コンストラクタで直接渡します
    固定長配列を用意しなくてもリテラルで渡せます
    ----------------------------------------------- }
  PrintCurseEnergyStats('Nobara Kugisaki(釘崎野薔薇)',
                        [730, 810, 790]);

  { -----------------------------------------------
    要素数 1 の配列コンストラクタも渡せます
    ----------------------------------------------- }
  PrintCurseEnergyStats('Nanami Kento(七海建人)', [1200]);

  { -----------------------------------------------
    String の配列を渡します
    伏黒恵の十種影法術を表示します
    ----------------------------------------------- }
  fushiguro_techniques[1] := '玉犬(白・黒)';
  fushiguro_techniques[2] := '嵌合暗翳庭(はめあいあんえいてい)';
  fushiguro_techniques[3] := '十種影法術';

  ListTechniques('Megumi Fushiguro(伏黒恵)', fushiguro_techniques);

  { 配列コンストラクタで String を渡す例 }
  ListTechniques('Satoru Gojo(五条悟)',
                 ['無下限呪術', '蒼(引力)', '赫(斥力)', '紫(虚式)']);

  { -----------------------------------------------
    var 引数と組み合わせてオープン配列の最大値を取得します
    虎杖悠仁の呪力値から最大値とそのインデックスを探します
    ----------------------------------------------- }
  WriteLn('--- 最大呪力値の探索(FindMaxEnergy) ---');
  FindMaxEnergy(itadori_energies, best_val, best_idx);
  WriteLn('  Yuji Itadori の最大呪力値: ', best_val,
          '  インデックス: ', best_idx);
  WriteLn('');

  { -------------------------------------------
    釘崎野薔薇の呪力値でも同様に確認します
    ----------------------------------------------- }
  kugisaki_energies[1] := 730;
  kugisaki_energies[2] := 810;
  kugisaki_energies[3] := 790;

  FindMaxEnergy(kugisaki_energies, best_val, best_idx);
  WriteLn('  Nobara Kugisaki の最大呪力値: ', best_val,
          '  インデックス: ', best_idx);
  WriteLn('');

  { -----------------------------------------------
    array of const — 型混在の可変長引数
    五条悟のプロフィールを異なる型で渡します
    ----------------------------------------------- }
  WriteLn('--- array of const(PrintProfile) ---');
  WriteLn('  Satoru Gojo(五条悟)のプロフィール:');
  PrintProfile(['Satoru Gojo', 28, True, '特級術師']);
  WriteLn('');

  WriteLn('  Kento Nanami(七海建人)のプロフィール:');
  PrintProfile(['Kento Nanami', 27, True, '1級術師']);
  WriteLn('');

  WriteLn('==========================================');
end.
fpc jjk_open_array.pas && ./jjk_open_array
Free Pascal Compiler version ...
Linking ./jjk_open_array
===== 呪術廻戦 オープン配列サンプル =====


--- Yuji Itadori(虎杖悠仁) の呪力値リスト ---
  要素数: 4
  [0] 920
  [1] 980
  [2] 1050
  [3] 1100
  合計  : 4050
  平均  : 1012

--- Nobara Kugisaki(釘崎野薔薇) の呪力値リスト ---
  要素数: 3
  [0] 730
  [1] 810
  [2] 790
  合計  : 2330
  平均  : 776

--- Nanami Kento(七海建人) の呪力値リスト ---
  要素数: 1
  [0] 1200
  合計  : 1200
  平均  : 1200

--- Megumi Fushiguro(伏黒恵) の術式 ---
  1. 玉犬(白・黒)
  2. 嵌合暗翳庭(はめあいあんえいてい)
  3. 十種影法術

--- Satoru Gojo(五条悟) の術式 ---
  1. 無下限呪術
  2. 蒼(引力)
  3. 赫(斥力)
  4. 紫(虚式)

--- 最大呪力値の探索(FindMaxEnergy) ---
  Yuji Itadori の最大呪力値: 1100  インデックス: 3

  Nobara Kugisaki の最大呪力値: 810  インデックス: 1

--- array of const(PrintProfile) ---
  Satoru Gojo(五条悟)のプロフィール:
  [AnsiStr ] Satoru Gojo
  [Integer ] 28
  [Boolean ] TRUE
  [AnsiStr ] 特級術師

  Kento Nanami(七海建人)のプロフィール:
  [AnsiStr ] Kento Nanami
  [Integer ] 27
  [Boolean ] TRUE
  [AnsiStr ] 1級術師

==========================================
jjk_vtype_case.pas

TVarRecのVTypeを使って型を判別し、それぞれの型に応じた処理を分ける例です。

{$mode objfpc}
program jjk_vtype_case;

procedure PrintValue(const args : array of const);
var
  i : Integer;
begin
  for i := 0 to High(args) do begin
    case args[i].VType of
      vtInteger    : WriteLn('  Integer : ', args[i].VInteger);
      vtBoolean    : WriteLn('  Boolean : ', args[i].VBoolean);
      vtChar       : WriteLn('  Char    : ', args[i].VChar);
      vtAnsiString : WriteLn('  String  : ', AnsiString(args[i].VAnsiString));
    else
      WriteLn('  Other (VType=', args[i].VType, ')');
    end;
  end;
end;

begin
  WriteLn('===== VType による型判別 =====');
  WriteLn('--- Satoru Gojo(五条悟) ---');
  PrintValue(['Satoru Gojo', 28, True]);
  WriteLn('');
  WriteLn('--- Megumi Fushiguro(伏黒恵) ---');
  PrintValue(['Megumi Fushiguro', 15, False]);
  WriteLn('==============================');
end.
fpc jjk_vtype_case.pas && ./jjk_vtype_case
Free Pascal Compiler version ...
Linking ./jjk_vtype_case
===== VType による型判別 =====
--- Satoru Gojo(五条悟) ---
  String  : Satoru Gojo
  Integer : 28
  Boolean : TRUE

--- Megumi Fushiguro(伏黒恵) ---
  String  : Megumi Fushiguro
  Integer : 15
  Boolean : FALSE
==============================
jjk_util_format.pas

array of constを受け取るユーティリティ関数の例です。任意の型の値を整形して文字列として返します。

{$mode objfpc}
program jjk_util_format;

uses SysUtils;

function FormatValues(const args : array of const) : String;
var
  i      : Integer;
  result_str : String;
begin
  result_str := '';
  for i := 0 to High(args) do begin
    if i > 0 then result_str := result_str + ', ';
    case args[i].VType of
      vtInteger    : result_str := result_str + IntToStr(args[i].VInteger);
      vtBoolean    : if args[i].VBoolean then
                       result_str := result_str + 'true'
                     else
                       result_str := result_str + 'false';
      vtAnsiString : result_str := result_str + AnsiString(args[i].VAnsiString);
    else
      result_str := result_str + '?';
    end;
  end;
  FormatValues := '[' + result_str + ']';
end;

begin
  WriteLn('===== array of const ユーティリティ関数 =====');
  WriteLn('  Yuji Itadori: ', FormatValues(['Yuji Itadori', 15, True]));
  WriteLn('  Nobara Kugisaki: ', FormatValues(['Nobara Kugisaki', 16, True]));
  WriteLn('  Aoi Todo: ', FormatValues(['Aoi Todo', 18, False]));
  WriteLn('=============================================');
end.
fpc jjk_util_format.pas && ./jjk_util_format
Free Pascal Compiler version ...
Linking ./jjk_util_format
===== array of const ユーティリティ関数 =====
  Yuji Itadori: [Yuji Itadori, 15, true]
  Nobara Kugisaki: [Nobara Kugisaki, 16, true]
  Aoi Todo: [Aoi Todo, 18, false]
=============================================

よくあるミス

vtStringとvtAnsiStringの混同

ShortString型のリテラルは『vtString』、AnsiString型(通常の『String』)は『vtAnsiString』として渡されます。Free Pascalでは文字列リテラルは通常『vtAnsiString』として渡されます。『VType』を確認せずに『VString』フィールドを参照しようとすると、型が一致しない場合にアクセス違反になります。

VString^のデリファレンスを忘れる

『TVarRec.VString』は『PShortString』(ShortStringへのポインタ)です。実際の文字列値を得るには『VString^』のようにポインタを参照外しする必要があります。『VString』をそのまま使おうとするとポインタ値が渡され、意図した文字列にはなりません。

概要

『Pascal』のオープン配列パラメータ(『array of T』)を使うと、呼び出し元がどのサイズの配列を渡しても同じ手続き・関数で処理できます。インデックスは常に『0』始まりに正規化されるため、呼び出し元の配列が『array[1..10]』であっても手続き内では『0』から『9』でアクセスします。『High(arr)』で最大インデックスを、『Length(arr)』で要素数を取得できます。配列コンストラクタ(『[値1, 値2, ...]』)を使えば、固定長配列変数を用意せずにリテラルをそのまま渡すことも可能です。『array of const』は『WriteLn』と同様の「型を問わない可変長引数」を実現する仕組みで、各要素は『TVarRec』レコードとして渡され、『VType』フィールドで型を判定してから対応するフィールドを参照します。配列の基本については 配列(ARRAY)の基本 を、動的配列については 動的配列(Dynamic Array) を、パラメータ渡しの基本については パラメータ渡し(値渡し・VAR引数・CONST引数) を合わせて確認してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。