お知らせ

電子会議

ライブラリ

FDelphi サイト全文検索

Delphi FAQ一覧

サンプル蔵



FDelphi FAQ
15番会議室「FAQ編纂委員会」に寄せられた「よくある質問の答え」

[Q]
 一次元配列を動的に確保して使う方法はわかりましたが,2次元の配列 で同様にやるにはどうしたらよいですか?

[A]
 一つの解決法は,一次元の配列をたくさん確保しながら,それへの
ポインタをひとつづつ拾ってこれを配列に入れるやり方ですが,
それぞれの一次元配列をばらばらととってくるので,連続した大きな
領域にならない可能性があるのがたまにきずです.
 そこで,変数領域は一気にがばっととってきて,それを一次元の
配列がずらっとならんでいると見立てて,ポインタを順番にあてがう
やりかたにしてみました.
[例]
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Mask, ComCtrls, Grids;

type
  TForm1 = class(TForm)
    Button1: TButton;
    StringGrid1: TStringGrid;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

// 二次元配列を動的に確保して使う一般的な方法の例
// 行列は「一次元配列へのポインタの配列」として扱うが
// メモリの確保は一括してまとめて行う
// 添え字は0からに固定
{
ベクトルの要素へのアクセス
 pV:N個の要素を持つ配列へのポインタ

   ^  pV^[0]
   |  pV^[1]
   N
   |
   v  pV^[N-1]

行列の要素へのアクセス
  pM:NJ個の要素を持つ配列へのポインタの配列へのポインタ

      <------------ NI ------------->
   ^  pM^[0][0]        pM^[NI-1][0]
   |  pM^[0][1]
  NJ
   |
   v  pM^[0][NJ-1]     pM^[NI-1][NJ-1]
}
const
  Ndim = 1500;       {Maximam Vector size that you can change}
type
  TVector = array[0..Ndim-1] of double;
  PVector = ^TVector;
  PMatrix = array[0..Ndim-1] of PVector;

implementation

{$R *.DFM}

procedure Keisan(NI, NJ: integer; Grid: TStringGrid);
var
  I,J : Integer;
  pM : ^PMatrix;
  pV1, pV2 : PVector;
  tempP : Pointer;
begin
  // メモリの確保
  // ベクトル
  pV1 := AllocMem(NI * SizeOf(Double));        // 数値が入る領域1
  pV2 := AllocMem(NJ * SizeOf(Double));        // 数値が入る領域2

  // 行列
  pM := AllocMem(NI * SizeOf(Pointer));  // ヘ゛クトルへのホ゜インタの配列
  tempP := AllocMem(NI * NJ * sizeof(Double));// 数値が入る領域3
  for I := 0 to NI-1 do begin
    pM^[I] := Pointer(Longint(tempP) + I * NJ * SizeOf(Double));
  end;

  try
    // 値の取り込み例
    for I := 0 to NI-1 do begin            // Gridの1列目を取り込み
      pV1^[I] := StrToFloat(Grid.Cells[1,I+1]);
    end;
    for J := 0 to NJ-1 do begin            // Gridの2列目を取り込み
      pV2^[J] := StrToFloat(Grid.Cells[2,J+1]);
    end;


    // 実際の計算(かけ算の例)
    for I := 0 to NI-1 do begin
      for J := 0 to NJ-1 do begin
        pM^[I][J] := pV1^[I]  * pV2^[J];  // 要素へのアクセスの記述例
      end;
    end;

    // 結果の表示
    for I := 0 to NI-1 do begin
      for J := 0 to NJ-1 do begin
        Grid.Cells[I+1,J+1] := FloatToStr(pM^[I][J]);
      end;
    end;

  finally
    // 使ったメモリの廃棄
    FreeMem(pM^[0], NI * NJ * SizeOf(Double));
    FreeMem(pM, NI * SizeOf(Double));
    FreeMem(pV1, NI * SizeOf(Double));
    FreeMem(pV2, NJ * SizeOf(Double));
  end;
end;

// Gridにはイカのように入力しておく
{
   --- --- ---
   ---  1   1
   ---  2   2
   --- ---  3
   --- ---  4
   --- ---  5
}
procedure TForm1.Button1Click(Sender: TObject);
begin
  Keisan( 2, 5 ,StringGrid1); // 要素数が数値として渡される
end;

end.


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum FDELPHIに寄せられる質問の中から、よくある質問への回答を FDELPHIのメンバーがまとめたものです。 したがって、これらの回答はボーランド株式会社がサポートする公式のものではなく、掲示されている内容についての問い合わせは受けられない場合があります。

Copyright 1996-1998 Delphi Users' ForumFAQ編纂委員会