在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;