配列の書き込みと読み込みについての質問です。


あすなろV  2016-12-16 04:48:35  No: 48441

pTPerson = ^TPerson;
  TPerson = record
    Age : Integer;
    Name: AnsiString[30];
  end;
  TPersonArray = array of TPerson;

//動的レコード型配列書込
procedure TForm1.FileSave(fName: AnsiString)
var
  i,j: Integer;
  buf: array[1..16] of AnsiChar;  //buf :AnsiString[16];  ではダメらしい
  Fs : TFileStream;
  R  : TPersonArray;
begin
  SetLength(R, 100);  //配列のサイズを決定
  for i := 0 to 99 do
  begin
    R[i].Age := Random(100);
    for j := 1 to 16 do buf[j] := Chr( Random(26)+97 );
    //buf :AnsiString[16]; ではどういうわけか buf[j] が文字にならない!
    R[i].Name := 'Stream '+buf;
  end;

  Fs := TFileStream.Create(fName,fmCreate);
  try
    Fs.Write(R[0], SizeOf(TPerson)*Length(R)); //Length(R)で配列要素数がわかる
    //配列名は先頭アドレスを示すはずだが
    //Fs.Write(R, SizeOf(TPerson)*Length(R));
    //ではダメである。なぜ?
  finally
    Fs.Free;
  end;
end;

//動的レコード型配列読込
procedure TForm1.FileLoad(fName: AnsiString);
var
  i,L: Integer;
  Fs : TFileStream;
  R  : TPersonArray;
begin
  Fs := TFileStream.Create(fName,fmOpenRead or fmShareExclusive);
  try
    L := Fs.Size div SizeOf(TPerson); //L = 配列要素数
    SetLength(R, L);
    Fs.Read(R[0], Fs.Size); 
    //Fs.Read(R, Fs.Size); ではダメ!
    for i := 0 to L-1 do
      Memo1.Lines.Add( Format('%2d',[ R[i].Age ])+'   '+R[i].Name);
  finally
    Fs.Free;
  end;
end;
-------------------------------------------------------
FileSave で
  Fs.Write(R, SizeOf(TPerson)*Length(R));

FileLoad で
  Fs.Read(R, Fs.Size); 

とした場合ダメなのはなぜでしょうか?


通りすがり  2016-12-16 09:54:43  No: 48442

ずばりTPersonArrayが実際には動的配列だから、です。動的配列は
http://docwiki.embarcadero.com/RADStudio/Berlin/ja/%E5%8B%95%E7%9A%84%E9%85%8D%E5%88%97#.E5.8B.95.E7.9A.84.E9.85.8D.E5.88.97
の説明にあるように『動的配列変数は暗黙のポインタ』なのです。つまりこの場合のRは確保された動的配列の
領域を示す単なるポインタです。TStream.Read/Writeの第1パラメータはvar付きであり、そこにはメモリ上に
存在する実体が必要なのでうまくいかない(読み書きの対象がポインタ型の変数そのものになる)のです。


あすなろⅤ  2016-12-16 20:32:35  No: 48443

回答ありがとうございます。
  上のコードでヲサメヲサを静的配列にしたら
  ニョラィメャヲサモマィヤミゥェフィメゥゥサヲサ
でヲサマヒヲサです。そこでちょっと確認したいことがあります。

ヲサヲサノチコヲサローョョケケャヲサーョョケケンヲサヲサノサ

ヲサヲサチノヲサヲサコノチサ
ヲサヲサミヲサヲサヲサコミサ
ヲサヲサニヲサヲサコヤニモサ
ヲサヲサャヲサコノサ

ヲサヲサヲサヲサヲサヲサコスヲサーヲサヲサケケヲサ
ヲサヲサヲサヲサヲサヲサヲサヲサコスヲサーヲサヲサケケュアヲサ
ヲサヲサヲサヲサヲサヲサヲサヲサノチチロャンヲサコスヲサメィアーーーゥォオーサ

  ヤニモヲサでは
ヲサヲサヲサヲサニョラィニノチチローャーンャヲサモマィノゥェフヲサゥサ
ヲサヲサヲサヲサニョラィニノチチャヲサモマィノゥェフヲサゥサヲサヲサヲサヲサヲサヲサヲサ………ィ」ゥ
のどちらでもヲサマヒヲサですが、これはヲサニノチチローャーンヲサとヲサニノチチヲサのアドレスが同じというだけで
ヲサヲサヲサヲサニノチチローャーンヲサスヲサニノチチ
ではないのですから、ィ」ゥの記述はヲサニノチチヲサというヲサァ配列名ァヲサはポインタのように感じられます。しかし、
ヲサヲサヲサヲサミヲサコスヲサニノチチサ
とするとコンパイラに怒られます。トヲサのヲサァ静的配列名ァヲサはポインタではないのしょうか。教えていただいたリンク先のヘルプでもそんな説明はないようです。ヘモュトマモ時代の大昔ヲサテヲサを少しかじっていたことがあって、そのときの記憶でヲサテヲサの配列名はポインタであるというの頭の中に残っているものですから、ちょっと気になります。
スススススススススススススススススススススススススススススススススススススススス
ニコ あすなろV
トコ イーアカッアイッアカィ金ゥ アウコオーコーク シ  スュアセシ初心者セ シッニセシノヘヌ ス「コッッョョョッッアョ「 ス「ー「セ 書込者ノト:ロ 」、メァ・フ ノセタク
ケ  オア ン

あれ、ここ削除できないのかな?

コードがめちゃくちゃでしたィ゛゛サゥ

ヲサヲサノチコヲサローョョケケャヲサーョョケケンヲサヲサノサヲサ

ヲサヲサチノヲサヲサコノチサヲサ
ヲサヲサミヲサヲサヲサコミサヲサ
ヲサヲサニヲサヲサコヤニモサヲサ
ヲサヲサャヲサコノサヲサ

ヲサヲサヲサヲサヲサヲサコスヲサーヲサヲサケケヲサヲサ
ヲサヲサヲサヲサヲサヲサヲサヲサコスヲサーヲサヲサケケュアヲサヲサ
ヲサヲサヲサヲサヲサヲサヲサヲサチノロャンヲサコスヲサメィアーーーゥォオーサヲサ

  ヤニモヲサではヲサ
ヲサヲサヲサヲサニョラィチノローャーンャヲサモマィノゥェフヲサゥサヲサ
ヲサヲサヲサヲサニョラィチノャヲサモマィノゥェフヲサゥサヲサヲサヲサヲサヲサヲサヲサ………ィ」ゥヲサ
のどちらでもヲサマヒヲサですが、これはヲサチノローャーンヲサとヲサチノヲサのアドレスが同じというだけでヲサ
ヲサヲサヲサヲサチノローャーンヲサスヲサチノ
ではないのですから、ィ」ゥの記述はヲサチノヲサというヲサァ配列名ァヲサはポインタのように感じられます。ヲサ
スススススススススススススススススススススススススススススススススススススススス
ニコ あすなろV
トコ イーアカッアイッアカィ金ゥ アエコアカコオイ  書込者ノト:ロ 」、メァ・フ ノセタク
ケ  オア ン
モコ 

自己解決しました。スレ汚しごめん<ィ゜ヲサ゜ゥ>
スススススススススススススススススススススススススススススススススススススススス
ニコ 
トコ イーアカッアイッアカィ金ゥ アエコウキコアカ  書込者ノト:ロ 」 ァ」ハノJ

 ン

ヤニモョラは次のように宣言されています。
ヲサラィヲサツサヲサテコヲサフゥコヲサフサ

この第一引数の宣言の仕方は「定数パラメータ」というものです。
かつ、明示的に型を指定していないので「型なしパラメータ」です。

このような型なしパラメータは、適切なポインタや配列の型にキャストしてやることで渡された元の変数を参照することができます。
決してポインタを渡しているわけではないし、配列名がポインタとして扱われているわけでもありません。
渡された先(この場合はラメソッド)が、型のないパラメータをおそらくバイトの配列とみなしてアクセスしている、その結果がどちらも同じになったというだけです。

このようなパラメータの概念については、ヘルプのヲサトリファレンス→ト言語ガイド→手続きと関数ヲサで説明されています。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加