Безопасное удаление элементов из TStringList в Delphi
При работе с коллекциями в программировании часто возникают ситуации, когда необходимо удалить элемент из списка во время его обхода. В Delphi такая операция может привести к ошибке "Index out of bounds", если не соблюдать определенные правила. В данной статье мы рассмотрим, как безопасно удалять элементы из TStringList и избегать указанной ошибки.
Проблема
Пример кода, представленный в вопросе, демонстрирует проблему, с которой сталкиваются разработчики при удалении элементов из TStringList во время его обхода:
procedure TForm1.Button3Click(Sender: TObject);
var
tempId, i: Integer;
begin
tempId := StrToInt(Edit5.Text);
Plik := TStringList.Create;
Plik.LoadFromFile('.\klienci\' + Linia_Klient[Id + 1] + '.txt');
if Plik.Count = 1 then
begin
Label6.Caption := 'then';
if tempId = StrToInt(Plik[0]) then
begin
Label6.Caption := 'Zwrócono';
Plik.Delete(0);
end;
end
else
for i := 0 to Plik.Count - 2 do
begin
if tempId = StrToInt(Plik[i]) then
begin
Label6.Caption := 'Zwrócono';
Plik.Delete(i);
end;
end;
Plik.SaveToFile('.\klienci\' + Linia_Klient[Id + 1] + '.txt');
Plik.Free;
end;
При удалении элементов во время обхода списка с использованием цикла for от 0 до plik.Count - 2 или plik.Count - 1 возникает ошибка "Index out of bounds", так как удаление элемента приводит к изменению индексации оставшихся элементов.
Решение
Чтобы избежать ошибки "Index out of bounds", необходимо использовать цикл, который идет в обратном направлении, начиная с последнего элемента списка:
for i := Plik.Count - 1 downto 0 do
begin
if tempId = StrToInt(Plik[i]) then
begin
Label6.Caption := 'Zwrócono';
Plik.Delete(i);
end;
end;
Использование такого подхода позволяет безопасно удалять элементы, так как индексы оставшихся элементов не изменяются после удаления.
Альтернативные решения
Существуют и другие способы решения проблемы, например, использование цикла while, который пересчитывает количество элементов после каждого удаления:
var
i: Integer;
begin
i := 0;
while i < Plik.Count do
begin
if tempId = StrToInt(Plik[i]) then
begin
Label6.Caption := 'Zwrócono';
Plik.Delete(i);
// Уменьшаем индекс, чтобы компенсировать удаление элемента
i := i - 1;
end
else
Inc(i);
end;
end;
Также можно создать временный список и копировать в него только те элементы, которые не удаляются, а затем скопировать обратно в исходный список.
Заключение
При работе с TStringList в Delphi важно помнить о правилах безопасного удаления элементов. Использование обратного цикла for является наиболее простым и эффективным способом решения этой задачи. Следуя этим рекомендациям, можно избежать ошибок "Index out of bounds" и обеспечить корректную работу программы.
Приведены методы безопасного удаления элементов из `TStringList` в Delphi для избежания ошибки 'Index out of bounds' при обходе коллекции.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.