0

我创建了一个动态记录数组,使用此 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,PrjRecArray : Array of TPrjRec;并且不会以其他方式初始化。PrjSg 是包含在表单中的 tstringgrid,用于显示记录。

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

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

4

2 回答 2

5

您访问数组的末尾。代替

c := length(PrjRecArray);

c := length(PrjRecArray) - 1;

或者

c := high(PrjRecArray);

请记住,动态数组是从零开始的。

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

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

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

与动态数组相比,使用TList<T>可能会导致更简单的代码读写。您可以TList<T>处理调整其内部动态数组大小的细节。

我唯一的其他评论是我想知道数组的实际填充位置。您延长了长度,但我显然看不到您在哪里分配任何值。

于 2017-07-15T17:18:28.807 回答
4

Length给出数组的当前长度. 但是动态数组从 index 开始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);,这是相同的),并跟踪数组中实际使用的元素。这样可以避免使堆碎片化,这可能使您很容易耗尽内存。

在我关于扩展数组的博客文章中了解更多信息。

于 2017-07-15T17:24:51.287 回答