Reputation:
Are there any way to count how many elements there are in an array by using code?
for example:
arrName : array[1..20] of string;
I already know that there are 6 names stored in that array, but how can I use coding to determine that?
Upvotes: 5
Views: 11774
Reputation: 76567
Yes, but only if the array contains managed types.
Have a look at the following code sample.
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;
Note the empty string aka ''
is a valid string. If you allow the program to store empty strings in this array your scheme will fail; if so you'll need to initialize the array with a placeholder string.
Managed types are initialized empty
When you debug this sample and bring up the CPU window, you'll see the following initialization code:
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
In the begin
statement a call is made to InitializeArray
because the array contains string
.
Non-managed types are not initialized
If the array contains anything else it will not be initialized; meaning that it will contain whatever was in that piece of memory before.
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;
(Obviously a **dynamic** array
(an array without pre-set bounds) will be zeroed before use and when expanding)
This does not apply to class members
All members (aka fields) of a class are initialized to zero when an object (instance of that class) is created.
Global variables are also zero initialized. Variables local to a method are not.
Clever programming
If you are somehow forced to use a fixed length array to store a variable number of strings, it is wasteful to count the number of items by traversing the array.
Much better to have a counter in place that keeps track of the number of elements.
type
TNames = record
count: integer;
items: array[0..20] of string;
end;
Otherwise you'll fall into a Schlemiel the painter trap; a well known antipattern.
Upvotes: 8
Reputation: 28806
So you have a fixed size array of 20 elements, but not all of them are valid strings.
One option is to keep track of the number of valid items when you fill the array, in a special variable. This variable starts with 0, and each time you add a string to the array, you increment it. This assumes that all valid items are in a contiguous range from the start of the array (i.e. there are no gaps, and "empty" items are only found at the end). This is how classes like TList
keep track of the count of their items.
In this case, because the items are strings, you can simply count the valid strings. Strings are initialized to ''
, so you can simply test for ''
. To make things easier later on, first define a type for the array. Then you can declare a variable of that type and re-use that type in a parameter declaration.
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;
Of course this only works if ''
is not a valid entry.
Upvotes: 0
Reputation: 1570
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;
You could also create a function to count your array for you:
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;
Upvotes: 0