首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 數學運算式計算:以 ADO 引擎實作與例外處理最佳實務

     編輯:Delphi

前言

計算字串形式的數學運算式 (如 "3.14 * (5 + 2) / 2") 是常見需求。本文展示一種巧思:利用 Microsoft Jet OLE DB Provider 對 dBASE 檔案的 SQL 查詢能力,零解析器實作即可支援四則運算、邏輯運算、數學函數 (SIN、COS 等) 及字串函數。並深入探討 Delphi 兩大例外處理模式 try...except 與 try...finally 的適用場景。

核心計算函式


function CalcExpr(const Expr: string): string;
var
  Query: TADODataSet;
begin
  Query := TADODataSet.Create(nil);
  try
    // 使用 Jet OLE DB Provider 的 dBASE 驅動
    Query.ConnectionString :=
      'Provider=MSDASQL.1;Persist Security Info=False;' +
      'Data Source=dBASE Files';
    // SQL 查詢直接計算運算式
    Query.CommandText := 'SELECT ' + Expr + ' AS Result';
    Query.Open;
    Result := Expr + ' = ' + Query.FieldByName('Result').AsString;
  finally
    Query.Free;  // 確保資源釋放
  end;
end;

表單呼叫與例外處理


procedure TfrmCalc.Button1Click(Sender: TObject);
begin
  try
    Edit1.Text := CalcExpr(Edit1.Text);
  except
    on E: Exception do
      ShowMessage('計算錯誤:' + E.Message);
  end;
end;

procedure TfrmCalc.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #13 then Button1Click(Self);
end;

支援運算子與函數 (Jet SQL 子集)

範例:CalcExpr("SIN(3.14159/2)") → SIN(3.14159/2) = 1;CalcExpr("LEFT('Hello',2)") → LEFT('Hello',2) = He。

例外處理深度解析:try...except vs try...finally

try...except...end:捕獲錯誤並回應

  • 用於呼叫端,預期被呼叫程式碼可能拋出例外,需捕獲並處理 (顯示訊息、記錄日誌、重試、轉換例外類型)。
  • 範例:CalcExpr 可能因 SQL 語法錯誤、連線失敗拋出例外,UI 層捕獲並友善提示。
  • 可針對特定例外類型處理:on E: EDatabaseError do ...、on E: EConvertError do ...、on E: Exception do ... (捕獲其餘)。

try...finally...end:保證資源釋放

  • 用於資源擁有者 (配置記憶體、開啟檔案、建立物件、取得鎖定),確保無論正常返回或拋出例外,finally 區塊必定執行,完成清理工作。
  • 範例:CalcExpr 內部建立 TADODataSet,finally 區塊 Query.Free 保證不洩漏。
  • 不捕獲例外:例外會穿透繼續向上傳播,由上層決定如何處理。

為何無 try...except...finally 單一結構?

Delphi 故意分離兩種關注點:錯誤處理 (except) 與 資源管理 (finally)。需同時兼顧時巢狀使用:


Query := TADODataSet.Create(nil);
try
  try
    Query.CommandText := 'SELECT ' + Expr + ' AS Result';
    Query.Open;
    Result := Expr + ' = ' + Query.FieldByName('Result').AsString;
  except
    on E: Exception do
    begin
      LogError(E.Message);  // 記錄
      raise;                // 重新拋出讓上層處理
    end;
  end;
finally
  Query.Free;  // 無條件釋放
end;

優缺點與適用場景

類別範例
算術+、-、*、/、\ (整除)、MOD
邏輯AND、OR、XOR、NOT
比較=、<>、<、>、<=、>=
數學ABS、SQR、SIN、COS、TAN、ATN、EXP、LOG、SGN、SQR
字串LEFT、RIGHT、MID、LEN、TRIM、UCASE、LCASE
轉換CINT、CLNG、CSNG、CDBL、CSTR、CBOOL
優點缺點適用場景
零程式碼解析器,支援豐富函數需安裝 Jet/ACE Provider;效能不如原生解析器原型開發、腳本引擎、報表運算式、教學示範

安全性提醒

直接拼接使用者輸入至 SQL 存在注入風險 (雖 Jet SQL 無預存程序參數化支援)。生產環境建議:
1. 先以正規表示式驗證運算式只含允許字元。
2. 或改用專用運算式解析庫 (如 TExpressionParser、mXparser Pascal 移植版)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved