Name McChange Name McChange - 1 year ago 140
Pascal Question

Pascal: Got to subtract 1 from length to get right size

I've got a piece of code like this:

for I := 0 to Self.EventQueue.Count do

It bugs out when the Count is 0, because it tries to
a nonexisting element. When I change it to

for I := 0 to Self.EventQueue.Count-1 do

All works fine. Is there any elegant way to get around this or is this common practice?

Answer Source

This is absolutely normal behavior, and is documented in the help for every list and container class in Delphi/FreePascal. The reason is pretty clear - if you have three items in the list, and the first item is at index 0, then you have items 0, 1, 2 but a Count of 3, right?

for i := 0 to StringList.Count - 1 do  // TStringList

for i := 0 to List.Count - 1 do        // TList

for i := 0 to StringGrid1.ColCount do  // TStringGrid

The alternative isn't as clear (and to me is worse to type):

for i := 0 to Pred(StringList.Count) do  

Dynamic arrays start at index 0 as well.

  IntArray: array of Integer;
  i: Integer;
  SetLength(IntArray, 10);
  for i := Low(IntArray) to High(IntArray) do  // loop is 0..9

The only things that aren't 0 based in FPC/Delphi are string types, which start at 1, and non-dynamic arrays (ones that are declared with a fixed size in code), which can start at almost any index you want. For instance, this is perfectly legal:

  IntArray: array[-10..10] of Integer;
  i: Integer;
  for i := Low(IntArray) to High(IntArray) do // loop is -10..10

Just as an aside, any time you do anything in your loop that will reduce the number of items in your list, you should iterate backwards:

for i := List.Count - 1 downto 0 do

Otherwise, you'll iterate beyond the end of the list, because the Count is only evaluated at the time the loop starts.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download