【问题标题】:Using Length() with multi-dimensional dynamic arrays in Delphi在 Delphi 中将 Length() 与多维动态数组一起使用
【发布时间】:2010-09-14 20:00:48
【问题描述】:

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

这是执行此操作的正确方法还是有更好的方法来根据需要扩展数组?

【问题讨论】:

    标签: delphi arrays


    【解决方案1】:

    @PatrickvL: 对不起,但这完全是错误的。您的代码甚至无法编译,因为它试图为一维元素 List[x] 设置二维。 (PatrickvL 更新了他的代码,因此这部分答案不再有效。) em>

    以下代码演示了多维数组的大小调整。

    程序测试维度;

    {$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 帮助也很好地解释了这一点(结构化类型、数组)。

    多维动态数组 要声明多维动态数组,请使用 ... 构造的迭代数组。例如,

    type TMessageGrid = 字符串数组;
    var Msgs: TMessageGrid;

    声明一个二维字符串数组。要实例化此数组,请使用两个整数参数调用 SetLength。例如,如果我 和 J 是整数值变量,

    SetLength(Msgs,I,J);

    分配一个 I-by-J 数组,Msgs[0,0] 表示该数组的一个元素。

    您可以创建非矩形的多维动态数组。第一步是调用 SetLength,将数组的前 n 维参数传递给它。例如,

    var Ints:Integer 数组数组;
    设置长度(整数,10);

    为 Ints 分配 10 行但没有列。稍后,您可以一次分配一个列(给它们不同的长度);例如

    SetLength(Ints[2], 5);

    使 Ints 的第三列长为五个整数。此时(即使尚未分配其他列)您可以将值分配给第三列 - 例如 Ints[2,4] := 6。

    以下示例使用动态数组(以及在 SysUtils 单元中声明的 IntToStr 函数)来创建字符串的三角矩阵。

    变量
    A : 字符串数组的数组;
    I, J : 整数;
    开始
    SetLength(A, 10);
    对于 I := 低 (A) 到高 (A) 做
    开始
    SetLength(A[I], I);
    对于 J := Low(A[I]) to High(A[I]) do
    A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
    结束;
    结尾;

    【讨论】:

    • 感谢您指出这一点;我已经习惯了使用参差不齐的数组,以至于我从来没有想过 Delphi 也允许类似立方体的数组。尽管如此,读回这个问题,似乎参差不齐的数组 where 是主题,所以我的评论仍然有效,只要经过一点修正(pfew!)干杯!
    • 我同意——这里的问题措辞似乎是个问题。您对问题的解释完全有可能是正确的。
    【解决方案2】:

    我想你忘了在第二个维度上使用第二个索引;

    你的代码应该是这样的:

    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 一样)。 正因为如此,像上面那样增长数组是可行的,但是任何其他对它的引用仍然会有它的 old 副本!

    解决这个问题的唯一方法是使用一个额外的间接级别来跟踪这些数组 - 即。 : 使用指向动态数组的指针(它本身也是一个指针,不过没关系)。

    还请注意,在动态数组的地址可能发生变化的任何情况下,如使用 SetLength() 增大/缩小它时,应更新任何这些“外部”指针。

    【讨论】:

    • 如果您想创建参差不齐的数组 - 不同索引具有不同子维度长度的数组,您只需在子维度上调用 SetLength(即 SetLength(List[X], ...))。另外,这将创建要插入到 List[x] 的二维数组(希望编译器会抱怨)。
    【解决方案3】:

    对我来说看起来不错 - 如果您将最后一行更改为

    SetLength(List, Length(List), y + 1);
    

    【讨论】:

    • 可能是问题被编辑了,但您的代码示例与问题的最后一行没有什么不同!?
    • 是的,问题已被编辑,您可以通过单击问题底部“已编辑”文本右侧的链接来​​检查修改。
    猜你喜欢
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2012-12-13
    • 2013-01-09
    • 1970-01-01
    相关资源
    最近更新 更多