在删除项目时列出索引超出范围

时间:2016-04-02 16:07:01

标签: delphi listbox

我解决了我的问题,但我需要知道为什么会出现这个问题?!

我编写了一个项目,将文件加载到listBox,然后逐个删除字符串,

但是当我删除listBox字符串时,这个异常引起了我的兴趣!

列出索引超出范围(5)!

我输入这个循环读取列表框并删除字符串:

for i := 0 to ListBox3.Count -1  do
  begin
      ShowMessage(ListBox3.Items[i]);
       ListBox3.items.Delete(i);
  end;

通过在f​​or-loop语句中做一点改动来解决我的问题

for i := ListBox3.Items.Count - 1 downto 0 do
  begin
      ShowMessage(ListBox3.Items[i]);
       ListBox3.items.Delete(i);
  end;

为什么第一个语句引发了异常,第二个语句可以正常工作?

3 个答案:

答案 0 :(得分:7)

通过删除向前移动的项目,您可以切断您站立的分支。 :-)循环的上限仅在循环开始之前计算一次,如果删除项目,则列表中的项目现在比计算边界时更少。

  • 评估循环限制(例如,List.Count - 1 = 5)。有效索引是[0..4]
  • 循环开始,您检索List [0]并将其删除。清单计数= 4, 界限仍为5
  • 索引递增,您检索并删除List [1]。列表计数= 3,界限仍为5
  • 索引递增,您检索并删除List [2]。列表计数= 2,边界仍为5.
  • 索引递增,您检索List [3] - 糟糕!列表中只有2个项目,现在位于索引[0..1] - 列表索引超出范围(3)

通过向后迭代,即使边界仍然只在开头计算,你也可以从结尾删除项目并同时减少计数。

  • Bounds为5,您检索List [4]并将其删除。计数现在是4,界限仍然是5
  • 索引递减,您检索List [3]并将其删除。计数现在是3,界限仍然是5
  • 索引递减,您检索List [2]并将其删除。伯爵现在是2,界限仍然是5。
  • 索引递减,您检索并删除List [1]。伯爵现在是1,界限仍然是5。
  • 索引递减,您检索并删除List [0]。列表现在为空,但我们已达到循环的终止条件(downto 0)并且循环退出安全。

答案 1 :(得分:3)

每次从列表中删除项目时,列表中只包含一个项目。但是,for语句在开头复制列表计数,并且在每次迭代时不会更新。因此,当您到达列表的中途时,计数器i将变得大于当前(新)列表计数,即使列表不再包含原始项目数。

作为替代方案,你也可以这样做一个循环:

while ListBox3.Items.Count > 0 do begin
  ShowMessage(ListBox3.Items[0]);
  ListBox3.items.Delete(0);
end;

答案 2 :(得分:1)

当您不删除某些项目时,可能会出现这种情况。那么通用的方法就是

i := 0;
while i < ListBox3.Items.Count do
  begin
    ShowMessage(ListBox3.Items[i]);
    if <wantToDelete> then // some condition there
      ListBox3.Items.Delete(i)
    else
      Inc(i);
   end;