动态记录数组无法展开

时间:2017-07-15 17:04:16

标签: arrays delphi record delphi-10.2-tokyo

我创建了一个动态的记录数组,使用这个actionexecute方法进行扩展:

procedure TForm1.AddTeamActionExecute(Sender: TObject);
Var
  c : integer;
begin
  c := length(PrjRecArray);
  PrjRecArray[c].tmpLoadPrjRec (true, 'Team', 'Big Building', '123 Main Street' ,'',
    'Somewhere', 'Ohio','43210', '555-1234', 'Bob', 'Big Cheese', '555-0123', 'bob@gmail.com');

  PrjSg.Cells[0,PrjSg.RowCount-1] := (PrjRecArray[c].Team);
  PrjSg.Cells[1,PrjSg.rowcount-1] := (PrjRecArray[c].Name);
  PrjSg.Cells[2,PrjSg.rowcount-1] := (PrjRecArray[c].addr1);
  PrjSg.Cells[3,PrjSg.rowcount-1] := (PrjRecArray[c].addr2);
  PrjSg.Cells[4,PrjSg.rowcount-1] := (PrjRecArray[c].city);
  PrjSg.Cells[5,PrjSg.rowcount-1] := (PrjRecArray[c].state);
  PrjSg.Cells[6,PrjSg.rowcount-1] := (PrjRecArray[c].zip);
  PrjSg.Cells[7,PrjSg.rowcount-1] := (PrjRecArray[c].phone);
  PrjSg.Cells[8,PrjSg.rowcount-1] := (PrjRecArray[c].contact);
  PrjSg.Cells[9,PrjSg.rowcount-1] := (PrjRecArray[c].title);
  PrjSg.Cells[10,PrjSg.rowcount-1] := (PrjRecArray[c].conPhone);
  PrjSg.Cells[11,PrjSg.rowcount-1] := (PrjRecArray[c].email);
  PrjSg.RowCount := PrjSg.RowCount + 1;
  Revised(true);
  showmessage ('PrSG Rows = ' + inttostr (PrjSg.RowCount));
  c := c + 1;
  SetLength (PrjRecArray, c);
  showmessage ('PrjRecArray Rows = ' + inttostr (length(PrjRecArray)));

end;

该数组在单元(PrjRecArray : Array of TPrjRec;)中声明为PrjRecArray,未以其他方式初始化。 PrjSg是一个包含在表单中的tstringgrid,用于显示记录。

当我使用AddTeamActionExecute添加更多记录时,stringgrid的大小会继续正确增加。但是,当PrjRecordArray正确扩展到四个记录时,程序显然在设置长度行的第五次迭代时失败。执行挂起,从不显示第二个showmessage框。

我是否错过了正确使用动态数组的一些步骤?

2 个答案:

答案 0 :(得分:5)

您可以访问数组的末尾。而不是

c := length(PrjRecArray);

c := length(PrjRecArray) - 1;

c := high(PrjRecArray);

请记住,动态数组是基于零的。

如果在编译器选项中启用了范围检查,那么对于任何超出范围的阵列访问,您将遇到运行时错误,这极大地有助于调试。

还需要更正对SetLength的调用。例如

SetLength (PrjRecArray, length(PrjRecArray) + 1);

使用TList<T>而不是动态数组可能会导致更简单的代码读写。您可以让TList<T>处理调整其内部动态数组大小的详细信息。

我唯一的另一个评论是我想知道数组实际填充的位置。你扩展了长度,但我不明白你在哪里分配任何值。

答案 1 :(得分:4)

Length给出数组的当前长度。但动态数组从索引0开始,它们以 - 在这种情况下 - High(PrjRecArray)结束。您应该访问PrjRecArray[c - 1],而不是PrjRecArray[c]

或者,使用

c := High(PrjRecArray);

然后你可以使用

PrjSg.Cells[0, PrjSg.RowCount - 1] := PrjRecArray[c].Team;
// etc...

在您的代码中,如果您已经有c的长度,然后再将长度设置为相同的c,那么您确实不是扩展,您是将它设置为已有的相同长度。使用

SetLength(PrjRecArray, Length(PrjRecArray) + 1);

或者,在您的代码中(假设c是长度):

SetLength(PrjRecArray, c + 1); // previous length + 1

FWIW,如果您经常这样做,您可能需要考虑增加更大块的大小(例如SetLength(PrjRecArray, c + c shr 1); - 或SetLength(PrjRecArray, c + c div 2);,这是相同的),并保持跟踪实际使用的数组元素。这样可以避免碎片碎片化,这可能会让你很容易耗尽内存。

有关扩展阵列的blog article更多信息。