我创建了一个动态的记录数组,使用这个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框。
我是否错过了正确使用动态数组的一些步骤?
答案 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更多信息。