6.2.7 記錄的刪除、插入、排序
刪除一條記錄的基本思路是:獲取當前記錄的位置并把該位置后的記錄逐個向前移動。 文件在最后一條記錄前截斷。
for i:=CurrentRec+1 to Count-1 do
begin
seek(MethodFile,i);
read(MethodFile,MethodRec);
seek(MethodFile,i-1);
Write(MethodFile,MethodRec);
end;
Truncate(MethodFile);
為避免誤刪除,在進行刪除操作前彈出一個消息框進行確認。刪除后要更新全局變量的值和顯示內容:
Count := Count - 1;
ChangeGrid;
完整的程序如下:
procedure TRecFileForm.DeleteButtonClick(Sender: TObject);
var
Newfile: MethodFileType;
MethodRec: TMethod;
NewFileName: String;
i: Integer;
begin
if FileOpened = False then Exit;
CurrentRec := StringGrid1.Row-1;
if CurrentRec < 0="" then="" exit;="">
if MessageDlg('Delete Current Record ?', mtConfirmation,
[mbYes, mbNo], 0) = idYes then
begin
HazAttr.text := '';
for I := CurrentRec+1 to Count-1 do
begin
seek(MethodFile,i);
read(MethodFile,MethodRec);
seek(MethodFile,i-1);
Write(MethodFile,MethodRec);
end;
Truncate(MethodFile);
Count := Count-1;
ChangeGrid;
end;
end;
這里所顯示的刪除操作簡單明了。但在程序開始設計時我卻走了一條彎路,后來發現雖然這種方法用于記錄的刪除操作顯得笨拙、可笑,但卻恰恰是記錄插入、排序的思想。
這種思想的核心是創建一個新文件保存更新后的內容。若新文件順利創建,則刪除原文件,否則恢復原來的文件。程序清單如下:
procedure TRecFileForm.DeleteButtonClick(Sender: TObject);
var
Newfile: MethodFileType;
MethodRec: TMethod;
NewFileName: String;
i: Integer;
begin
if FileOpened = False then Exit;
CurrentRec := StringGrid1.Row-1;
if CurrentRec < 0="" then="" exit;="">
if MessageDlg('Delete Current Record ?', mtConfirmation,
[mbYes, mbNo], 0) = idYes then
begin
HazAttr.text := '';
NewFileName := ChangeFileExt(FileName,'.sav');
try
AssignFile(NewFile,FileName);
ReWrite(NewFile);
Except
On EInOutError do
begin
Rename(MethodFile,FileName);
Exit;
end;
end;
for i := 1 to Count do
if I <> CurrentRec+1 then
begin
MethodRec := GridToRec(i);
Write(NewFile,MethodRec);
end;
closeFile(MethodFile);
try
AssignFile(MethodFile,Filename);
Reset(MethodFile);
except
on EInOutError do
begin
DeleteFile(FileName);
AssignFile(MethodFile,NewFileName);
Reset(MethodFile);
Rename(MethodFile,FileName);
Exit;
end;
DeleteFile(NewFileName);
Count:=Count-1;
ChangeGrid;
end;
end;
對于記錄插入,方法基本同上。對于排序,可先將關鍵域讀入排序,而后再按排序結果對應的記錄號順序重寫文件。
6.2.8 結果綜合
對不同方法的評估結果,可按一定的公式進行綜合。當用戶按下“計算”按鈕時,系統進行計算并把綜合結果寫入HazAttr只讀編輯框中。
為保證結果顯示的正確性,每次增加、修改、刪除操作確認后HazAttr編輯框清空。
6.2.9 編輯對話框的輸入檢查
當用戶單擊“增加”或“修改”按鈕時系統將彈出一個編輯對話框,讓用戶輸入或修改記錄內容。其中的三個編輯框,一個組合列表框分別對應TMethod 的四個域。由于TMethod的Result域必須是[0,1]間的小數,因此當用戶按OK鍵關閉對話框時應進行類型和范圍檢查。
在VB中我做過同樣的工作,那時需要對用戶輸入的鍵碼逐個進行判斷。但這種方法很繁瑣、很難做圓滿(如不能很好地支持編輯鍵)。而Object Pascal提供了更好的方法。這種方法的關鍵就在于它的類型轉換函數Val:
procedure Val(Str: String;var V; var Code: Integer);
V是由Str轉換成的整型或實型數。若字符串非法,則出錯位置返至Code;否則置Code為0。字符串非法并不會引發一個轉換異常。
如果轉換后的數超出了我們的范圍,則顯式把Code置為-1。最后統一通過檢測Code是否為0來判斷輸入是否合法。
我們把輸入檢查放在對話框的OnCloseQuery事件處理過程中。如輸入非法,則禁止對話框關閉,并將輸入焦點置于Result編輯框中。但假如用戶按了Cancel按鈕,則這種檢查是多余的。為此定義一個布爾變量IsCancel,對話框生成時置為False。假如用戶按下Cancel,則置為True,此時OnCloseQuery事件不進行輸入檢查。
對話框的OnCloseQuery事件處理過程的程序清單如下:
procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
Res: Real;
k: Integer;
begin
if IsCancel = False then
begin
val(Result.text,Res,k);
if (Res > 1) or (Res < 0)="" then="" k="" :="-1;">
if k <> 0 then
begin
MessageDlg('非法輸入 !',mtWarning,[mbOK],0);
Result.text := '';
CanClose := False;
Result.SetFocus;
end;
end;
end; [1] [2] [3] 下一頁
|