计算数组中的元素数量

时间:2016-10-08 21:49:41

标签: arrays delphi

有没有办法通过代码计算数组中有多少元素?

例如:

arrName   : array[1..20] of string;

我已经知道该数组中存储了6个名称,但是如何使用编码来确定?

3 个答案:

答案 0 :(得分:8)

是的,但仅当数组包含托管类型时 看看下面的代码示例。

procedure TForm1.Button1Click(Sender: TObject);
var
  sa: array[0..19] of string;
  i: Integer;
begin
  for i := 0 to 5 do
    sa[i]:= 'test'+IntToStr(i);
  for i := 6 to High(sa) do begin
    if sa[i] <> '' then ShowMessage('oops');  //will never be triggered.
  end;
end;

请注意,空字符串aka ''是有效字符串。如果您允许程序在此数组中存储空字符串,则您的方案将失败;如果是这样,您将需要使用占位符字符串初始化数组。

托管类型初始化为空
当您调试此示例并调出CPU窗口时,您将看到以下初始化代码:

Unit1.pas.30: begin
005C9B24 55               push ebp
005C9B25 8BEC             mov ebp,esp
......
005C9B3F E8F811E4FF       call @InitializeArray
......
Unit1.pas.31: for i := 0 to 5 do

begin语句中,调用InitializeArray,因为数组包含string

If the array contains: string, interface , dynamic array, variant or anonymous method (or records containing any of these) then it will be initialized.

未初始化非托管类型
如果数组包含其他任何内容,则不会对其进行初始化;这意味着它将包含之前在那段记忆中的任何内容。

procedure TForm1.Button1Click(Sender: TObject);
var
  sa: array[0..19] of integer;
  i: Integer;
begin
  for i := 0 to 5 do
    sa[i]:= i+1;
  for i := 6 to High(sa) do begin
    //will most likely be triggered
    if sa[i] <> 0 then ShowMessage('no init for integer');  
  end;
end;

(显然**dynamic** array(没有预设边界的数组)将在使用前和扩展时归零)

这不适用于班级成员
当创建对象(该类的实例)时,类的所有成员(也称为字段)都被初始化为零 Global variables are also zero initialized.方法的局部变量不是。

聪明的编程
如果以某种方式强制使用固定长度数组来存储可变数量的字符串,则通过遍历数组来计算项目数是浪费的。
最好有一个计数器来跟踪元素的数量。

type
  TNames = record
    count: integer;
    items: array[0..20] of string;
  end;

否则你将陷入Schlemiel the painter陷阱;一个众所周知的反模式。

答案 1 :(得分:0)

procedure TForm1.Button1Click(Sender: TObject);
var
  i, ArrayCount: integer;
  ArrName : Array[1..20] of string;
begin
  ArrayCount := 0;
  ArrName[1] := 'Bob';
  ArrName[2] := 'Bill';
  for i := low(ArrName) to high(ArrName) do
    if ArrName[i] <> '' then
      inc(ArrayCount);

  showmessage(IntToStr(ArrayCount));
end;

您还可以创建一个函数来为您计算数组:

function ArrayValueCount(const InputArray: Array of string): integer;
var
  i: integer;
begin
  result := 0;
  for i := low(InputArray) to high(InputArray) do
    if InputArray[i] <> '' then
      inc(result); 
end;

答案 2 :(得分:0)

所以你有一个包含20个元素的固定大小的数组,但并非所有元素都是有效的字符串。

一个选项是在填充数组时跟踪特殊变量中的有效项目数。此变量以0开头,每次向数组添加字符串时,都会增加它。这假定所有有效项目都在从阵列的开始处的连续范围内(即,没有间隙,并且仅在末尾找到“空”项)。这就是像TList这样的班级跟踪其项目数量的方式。

在这种情况下,因为项是字符串,所以您可以简单地计算有效字符串。字符串初始化为'',因此您只需测试''即可。为了使以后更容易,首先要为数组定义一个类型。然后,您可以声明该类型的变量,并在参数声明中重用该类型。

type
  TStringArray = array[1..20] of string;

var
  arrName: TStringArray;

function ItemCount(const A: array of string): Integer;
var
  I: Integer;
begin
  Result := 0;
  for I := Low(A) to High(A) do
    if A[I] <> '' then
      Inc(Result);
end;

当然,这仅在''不是有效条目时才有效。