在Delphi中将Length()与多维动态数组一起使用
时间:2020-03-06 15:01:51 来源:igfitidea点击:
我在delphi中使用多维动态数组,并试图弄清楚这一点:
对于第一个索引和第二个索引,我有2个单独的值,它们彼此完全分开。
随着新值的到来,如果该新值在任一范围之外,我想增加数组。
对于新值x,y
我检查:
if Length(List) < (x + 1) then SetLength(List, x + 1); if Length(List[0]) < (y + 1) then SetLength(List, Length(List), y + 1);
这是执行此操作的正确方法,还是有根据需要增加数组的更好方法?
解决方案
如果我们将最后一行更改为
SetLength(List, Length(List), y + 1);
我认为我们忘记了在第二维上使用第二个索引;
代码可能应如下所示:
if Length(List) < (x + 1) then SetLength(List, x + 1); if Length(List[x]) < (y + 1) then SetLength(List[x], y + 1);
请注意,在增大第二维时,将" x"用作第一维索引。
不过请注意以下几点:
我们应该意识到,Delphi也在动态数组上使用了引用计数(就像使用AnsiString一样)。
因此,可以像上面那样增长数组,但是对它的任何其他引用仍将具有它的旧副本!
解决此问题的唯一方法是使用一个额外的间接级别(即)来跟踪这些数组。 :使用指向动态数组的指针(本身也是一个指针,但是可以)。
还要注意,在动态数组的地址可能更改的任何情况下(例如使用SetLength()对其进行扩展/收缩时),都应更新这些"外部"指针中的任何一个。
@PatrickvL:
抱歉,但这完全是错误的。代码甚至没有编译,因为它试图为一维元素List [x]设置两个维度。 (PatrickvL更新了他的代码,因此答案的这一部分不再有效。)
以下代码演示了多维数组的大小调整。
程序TestDimensions;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
List: array of array of integer;
begin
//set both dimensions
SetLength(List, 3, 2);
Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 3, Y = 2
//set main dimension to 4, keep subdimension untouched
SetLength(List, 4);
Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 2
//set subdimension to 3, keep main dimenstion untouched
SetLength(List, Length(List), 3);
Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 3
//all List[0]..List[3] have 3 elements
Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //3333
//you can change subdimension for each List[] vector
SetLength(List[0], 1);
SetLength(List[3], 7);
//List is now a ragged array
Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //1337
//this does not even compile because it tries to set dimension that does not exist!
// SetLength(List[0], Length(List[0]), 12);
Readln;
end.
Delphi帮助也很好地解释了这一点(结构化类型,数组)。
Multidimensional Dynamic Arrays
To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I
and J are integer-valued variables,
SetLength(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.
You can create multidimensional dynamic arrays that are not rectangular. The first step is to call SetLength, passing it parameters for the first n dimensions of the array. For example,
var Ints: array of array of Integer;
SetLength(Ints,10);
allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); for example
SetLength(Ints[2], 5);
makes the third column of Ints five integers long. At this point (even if the other columns haven't been allocated) you can assign values to the third column - for example, Ints[2,4] := 6.
The following example uses dynamic arrays (and the IntToStr function declared in the SysUtils unit) to create a triangular matrix of strings.
var
A : array of array of string;
I, J : Integer;
begin
SetLength(A, 10);
for I := Low(A) to High(A) do
begin
SetLength(A[I], I);
for J := Low(A[I]) to High(A[I]) do
A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
end;
end;

