2

わかりました、私は自分が犯している可能性のあるすべての間違いを見つけようとしてきましたが、あきらめました...助けが必要です! 私が書いているのは、仕事のレンタルを管理するアプリで、日付が過ぎると、アプリは 2 つのテキスト ファイルから名前を削除します。これを機能させるために、3 つの小さな関数 (手順) を書きました。ここ:

これは、dates.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 つの日付を比較し、日付が今日または過去の場合に TRUE を返す単純な関数です。

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;

updatePerms プロシージャで remPerm に到達したときに発生するエラーです。(*) EStringList エラー、範囲外 (#) が発生します。従業員の期日が今日の場合にのみ発生することを何度も試してみました。さらに情報が必要な場合はコメントしてください!事前に感謝します。どんな助けも本当に感謝しています!

4

1 に答える 1

20

問題は、forループを使用していることです。forループの終点は、ループに入ったときに1回だけ評価されます。その時点で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

これは、従業員が複数回発生した場合に機能します。

ただし、従業員が1回だけ発生する場合は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ループを使用することです。

于 2011-11-22T04:46:53.257 に答える