Delphi для циклов и ошибок StringList - PullRequest
2 голосов
/ 22 ноября 2011

Хорошо, ребята, я пытался выяснить каждую возможную ошибку, которую я совершаю, но я сдаюсь ... Мне нужна помощь! То, что я пишу, - это приложение для управления арендной платой за мою работу, и когда дата истекает, мое приложение удаляет имя из 2 текстовых файлов. Я написал 3 маленьких функции (процедуры), чтобы сделать эту работу. Здесь:

Этот файл загружается из файла date.dat и удаляет строку, содержащую имя сотрудника.

procedure remDate(emp: String);/// Removes employee from date file
var
  pos1, i: integer;
  dateList: TStringList;
begin
  dateList:=TStringList.Create;
  dateList.LoadFromFile('Data\dates.dat');
  for i:=0 to dateList.Count-1 do begin
    pos1:=AnsiPos(emp, dateList[i]);
    if pos1<>0 then begin
      dateList.Delete(i);
      dateList.SaveToFile('Data\dates.dat');
    end;
  end;
  dateList.Free;
end; //eo remDate

Эта строка удаляет строку, содержащую имя сотрудника, из файла perm.dat.

procedure remPerm(emp: String);/// Removes employee from perm file
var
  pos1, i: integer;
  permList: TStringList;
begin
  permList:=TStringList.Create;
  permList.LoadFromFile('Data\perm.dat');
  for i:=0 to permList.Count-1 do begin
    pos1:=AnsiPos(emp, permList[i]);
    if pos1<>0 then begin
      permList.Delete(i);
      permList.SaveToFile('Data\perm.dat');
    end;
  end;
  permList.Free;
end; //eo remPerm

Этот склеивает их. IsDue - это простая функция, которая сравнивает 2 даты и возвращает ИСТИНА, если дата сегодня или прошла.

procedure updatePerms;
var
  empList: TStringList;
  i: integer;
begin
  empList:=TStringList.Create;
  empList.LoadFromFile('Data\employes.dat');
  for i:=0 to empList.Count-1 do begin
    if isDue(empList[i]) then begin
      remDate(empList[i]);
      remPerm(empList[i]);  (*) Here is where the error points.
    end;
  end;
  empList.Free;
end;

Ошибка, которую я получаю, это когда он получает remPerm в процедуре updatePerms. (*) Я получаю ошибку EStringList вне пределов (#). Со многими попытками выяснилось, что это происходит только тогда, когда у сотрудника наступает срок оплаты. Пожалуйста, прокомментируйте, если вам нужно больше информации! Заранее спасибо, любая помощь очень ценится!

1 Ответ

18 голосов
/ 22 ноября 2011

Проблема в том, что вы используете цикл for.Конечная точка цикла for оценивается только один раз при входе в цикл.В этот момент у вас может быть 100 элементов, но как только вы начнете удалять, их станет меньше.Это приведет к ошибке списка вне границ ошибка.

Простое исправление состоит в обращении цикла for:

procedure remDate(emp: String);
/// Removes employee from date file
var
  pos1, i: integer;
  dateList: TStringList;
begin
  dateList := TStringList.Create;
  dateList.LoadFromFile('Data\dates.dat');
  for i := dateList.Count - 1 downto 0 do
  begin
    pos1 := AnsiPos(emp, dateList[i]);
    if pos1 <> 0 then
    begin
      dateList.Delete(i);
      dateList.SaveToFile('Data\dates.dat');
    end;
  end;
  dateList.Free;
end; // eo remDate

. Это будет работать, еслиСотрудник встречается более одного раза.

Однако, если работник встречается только один раз, вы можете использовать break для раннего выхода из цикла:

procedure remDate(emp: String);
/// Removes employee from date file
var
  pos1, i: integer;
  dateList: TStringList;
begin
  dateList := TStringList.Create;
  dateList.LoadFromFile('Data\dates.dat');
  for i := 0 to dateList.Count - 1 do
  begin
    pos1 := AnsiPos(emp, dateList[i]);
    if pos1 <> 0 then
    begin
      dateList.Delete(i);
      dateList.SaveToFile('Data\dates.dat');
      Break; // <-- early exit
    end;
  end;
  dateList.Free;
end; // eo remDate

Другим решением является использованиеwhile петля.

...