动态记录数组无法展开
Dynamic Array of Records fails to expand
我创建了一个动态记录数组,使用此 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 正确扩展为四个记录,但程序显然在设置长度行的第五次迭代中失败。执行挂起,从不显示第二个显示消息框。
我是否遗漏了一些正确使用动态数组的步骤?
您访问了数组的末尾。而不是
c := length(PrjRecArray);
写
c := length(PrjRecArray) - 1;
或
c := high(PrjRecArray);
请记住,动态数组是从零开始的。
如果您在编译器选项中启用了范围检查,那么您将遇到任何越界数组访问的运行时错误,这对调试有很大帮助。
对 SetLength
的调用也需要更正。例如
SetLength (PrjRecArray, length(PrjRecArray) + 1);
而不是动态数组,使用 TList<T>
可能会导致更简单的代码读写。您可以让 TList<T>
处理调整其内部动态数组大小的细节。
我唯一的其他评论是我想知道数组实际填充的位置。你延长了长度,但我显然没有看到你在哪里赋值。
Length
给出数组的当前长度。但是动态数组从索引 0
开始,并且它们结束于 —— 在本例中 —— High(PrjRecArray)
。您应该访问 PrjRecArray[c - 1]
,而不是 PrjRecArray[c]
。
或者,使用
c := High(PrjRecArray);
然后你可以使用
PrjSg.Cells[0, PrjSg.RowCount - 1] := PrjRecArray[c].Team;
// etc...
在你的代码中,如果你已经有了 c
中的长度,然后再次将长度设置为相同的 c
,你确实没有 expanding,您将其设置为与已有长度相同的长度。使用
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 关于扩展数组的内容中有更多相关内容。
我创建了一个动态记录数组,使用此 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 正确扩展为四个记录,但程序显然在设置长度行的第五次迭代中失败。执行挂起,从不显示第二个显示消息框。
我是否遗漏了一些正确使用动态数组的步骤?
您访问了数组的末尾。而不是
c := length(PrjRecArray);
写
c := length(PrjRecArray) - 1;
或
c := high(PrjRecArray);
请记住,动态数组是从零开始的。
如果您在编译器选项中启用了范围检查,那么您将遇到任何越界数组访问的运行时错误,这对调试有很大帮助。
对 SetLength
的调用也需要更正。例如
SetLength (PrjRecArray, length(PrjRecArray) + 1);
而不是动态数组,使用 TList<T>
可能会导致更简单的代码读写。您可以让 TList<T>
处理调整其内部动态数组大小的细节。
我唯一的其他评论是我想知道数组实际填充的位置。你延长了长度,但我显然没有看到你在哪里赋值。
Length
给出数组的当前长度。但是动态数组从索引 0
开始,并且它们结束于 —— 在本例中 —— High(PrjRecArray)
。您应该访问 PrjRecArray[c - 1]
,而不是 PrjRecArray[c]
。
或者,使用
c := High(PrjRecArray);
然后你可以使用
PrjSg.Cells[0, PrjSg.RowCount - 1] := PrjRecArray[c].Team;
// etc...
在你的代码中,如果你已经有了 c
中的长度,然后再次将长度设置为相同的 c
,你确实没有 expanding,您将其设置为与已有长度相同的长度。使用
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 关于扩展数组的内容中有更多相关内容。