†Sibylのお部屋†

動的配列の代りにTListを使用する

作成開始日 2022.03.30
最終更新日 2022.04.12

以下、Sibylでは動的配列が使用できない事を前提としているが、本当のところは良く判らない。確かに、Sibylでは「array[1..5] of Integer」のように配列の添字のレンジ指定が必須で、Delphiのように「array of Integer」式の動的な配列宣言はできない。しかし、実際にはレンジ指定外の添字も使用可能なようだ。例えば、「x: array[1..5] of Integer」と宣言した場合でも、「x[8]:=…」行のコンパイルは通るし、機能も正常。実は隠し動的配列?う〜む、使える…のか?

Delphiでは動的配列が使用できるようだが、Sibyl/WDSibylでは使用できない。しかし、「TList型」は実質的にポインタの動的配列型なので、これをベースにすれば任意型の動的配列と同等の機能を実現できる。なお、「TStrings型」はこれまた実質的に動的な文字列型配列なので、文字列だけでよければ、こちらを使う方法もある(或は必要な情報をすべて文字列化するとかね)。

以下では、例として「TList型」を用いて整数列(Integer型)の動的配列を作成する

Type
  TpInt=^Integer;	//整数のポインタ型

Var
  n      : Intger;
  pN     : TpInt;	//整数型のポインタ
  myList : TList;	//作成する動的配列

Begin
  myList:=TList.Create;		//リストの生成、myList.Createでも可
  myList.Clear;			//一応、明示的に初期化しておく

  ///// 文字列の代入:実際はループで処理することが多いだろう

  //1番目の要素[0]の追加
  new(pN); 			//新しい整数型ポインタを作成
  pN^:=123; 			//ポインタの中身に値を代入
  myList.Add(pN);		//作成したポインタをリストに追加

  //以下、同様に任意個数だけ要素を追加可能
  new(pN); pN^:=999; myList.Add(pN);	//2番目の要素[1]の追加
  new(pN); pN^:=0  ; myList.Add(pN);	//3番目の要素[2]の追加
  new(pN); pN^:=52 ; myList.Add(pN);	//4番目の要素[3]の追加

  ///// 値の参照:明示的に型キャスト(TpInt)しないと「^」参照ができない
  n:=TpInt(myList.Items[0])^;	//「123」となる
  n:=TpInt(myList[2])^;		//「0」となる、「Items」を省略した形
  n:=Int(myList[2]);		//この形式が通れば便利だが…どうだろう?
ポイントは;

@「new」で新しいポインタを生成し、
A「^」で中身を設定し、
B「add」でリストに追加する=添字を付ける

と言う手順。追加する個数は任意で、一般的な配列のように予め上限を指定する必要はない。また、追加時にポインタを作成するため、必要以上のメモリも消費しない。ただし、上記のように、値の参照には型キャストが必要で、見栄えはよろしくない。

次に、もう少し実践的な例として、ファイル情報(ファイル名および各種属性)の一覧を取得して、動的配列に格納してみる。

Type
  TpSearchRec:=^TSearchRec;	//リストに格納するデータのポインタ型

Var
  rec     : TSearchRec;		//ファイル情報を格納(構造体)
  pRec    : TpSearchRec;	//recのアドレスを格納
  FileList: TList		//ファイル情報の動的配列
  fmask   : String;

Begin
  FileList:=TList.Create;
  FileList.Clear;

  fmask:='d:\mywork\*.*';		//「d:\mywork」のファイル一覧を取得する

  FindFirst(fmask, faDirectory, rec);	//1項目の[.]は読み飛ばし
  While FindNext(rec)=0 Do		//ループでファイル一覧を取得
  Begin
    new(pRec);
    pRec^:=rec;				//アドレスを渡せば全データにアクセス可能
    FileList.Add(pRec);			//アドレスをリストに追加
  End;

  //参照の仕方はこんな感じ(stは文字列型、lはロング整数型)
  st:=TpSearchRec(FileList[5])^.Name; //6番目のファイルの名前を取得
  st:=TSearchRec(FileList[5]).Name;   //多分この形式も通る、つかこっちが基本?
  l :=TpSearchRec(FileList[8])^.Size; //9番目のファイルのサイズを取得


【Sibylのお部屋目次】 【ホーム】