如果在运行时间之前我不知道长度,我该如何声明一个数组?

时间:2009-01-11 17:05:51

标签: delphi arrays global-variables dynamic-arrays redefine

我最初有一个数组[1..1000]被定义为全局变量。 但是现在我需要那个是n,而不是1000,直到后来才发现n。 我知道在填充数组之前n是什么,但我需要它是全局的,因此需要一种在运行时定义全局数组大小的方法。

Context正在填充一个数组,其中包含文件中字节的线性转换。 我不知道文件有多大,直到有人想打开它,文件可以是任何大小。

2 个答案:

答案 0 :(得分:89)

从Delphi 4开始,Delphi支持动态数组。您可以在运行时修改它们的大小,它们将保留您存储在旧大小的其他元素中的数据。它们可以包含任何同类型的元素,包括记录和其他数组。您可以声明一个动态数组,就像声明普通的“静态”数组一样,但只是省略数组边界:

var
  ArthurArray: array of TForm;

虽然静态数组允许您指定下限和上限,但动态数组的低索引始终为零。高索引由High函数给出,它总是返回一个小于数组长度的函数。对于任何动态数组xHigh(x) = Length(x)-1

任何代码都可以访问全局变量,包括本地过程。

动态数组类型的全局变量将初始化为数组。它的长度为零,并且在该数组上调用的High将为-1。该数组上的Low仍会返回零。

您可以随时调整动态数组的大小。使用SetLength功能,就像使用字符串一样:

var
  NumElements: Integer;
begin
  NumElements := GetNumberOfArthurForms();
  SetLength(ArthurArray, NumElements);
end;

如果你有一个多维数组,你可以在循环中设置它们的长度:

var
  matrix: array of array of Double;
  i: Integer;
begin
  SetLength(matrix, height);
  for i := 0 to height - 1 do
    SetLength(matrix[i], width);
end;

有一个快捷方式可以同时设置所有内部数组的长度:

begin
  SetLength(matrix, height, width);
end;

就像我提到的那样,动态数组在调整大小时会保留旧值:

var
  data: array of string;
begin
  SetLength(data, 2);
  data[1] := 'foo';
  SetLength(data, 20);
  Assert(data[1] = 'foo');
end;

但如果你缩短数组,那么任何超出新的最后一个元素的元素都将永远消失:

begin
  SetLength(data, 20);
  data[15] := 'foo';
  SetLength(data, 2);
  // data[15] does not exist anymore.
  SetLength(data, 16);
  writeln(data[15); // Should print an *empty* line.
end;

我上面的演示使用了字符串。字符串在Delphi中很特别;它们由编译器通过引用计数进行管理。因此,string类型的新动态数组元素被初始化为空。但是如果我使用了整数,那么就不能保证新元素的值。它们可能为零,但它们也可能是其他任何东西,就像独立局部变量的初始值一样。

Delphi 7帮助文件非常好,我被告知。请阅读有关动态数组的更多信息。您可以在Delphi安装中提供的VCL和RTL源代码中找到它们的使用示例,以及过去10年中生成的几乎所有Delphi代码示例。

答案 1 :(得分:1)

首先,这是对问题第一部分的一般回答:

如果您的数组不再是静态的,您可能需要考虑使用TListList,TStringList或Contnrs单元中的许多容器类之一。

它们可以更好地代表您正在做的事情,提供您可能需要的其他功能,例如:排序或名称/值对,它们会根据您的需要动态增长,并且已经过很好的优化。


然后你说:

  

“Context正在填充一个数组,其中包含文件中字节的线性转换。我不知道该文件有多大,直到有人想要打开它并且文件可以是任何大小。”

对于您的具体问题,我会使用以下命令在文件中加载字节:

  MyFileStream := TFileStream.Create(Filename, fmOpenRead or fmShareDenyWrite);
  Size := MyFileStream.Size - MyFileStream.Position;
  SetLength(Buffer, Size);
  MyFileStream.Read(Buffer[0], Size);

然后,您可以轻松地使用PChar指针逐个浏览每个字符甚至缓冲区中的每个字节,并按照您需要的方式对其进行转换。