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

Delphi 2009 TStringBuilder 進階:Replace 方法全方位替換技巧

     編輯:Delphi

Replace:高效字串替換核心

TStringBuilder.Replace 提供四種重載,支援字元/字串、全域/區間替換,內部優化緩衝區操作,效能遠優於傳統 StringReplace。

核心 API 四重載

重載參數說明
1. 字串全域OldStr, NewStr: string替換所有 OldStr 為 NewStr
2. 字元全域OldChar, NewChar: Char替換所有 OldChar 為 NewChar
3. 字元區間OldChar, NewChar: Char; StartIndex, Count: Integer指定範圍內替換字元
4. 字串區間OldStr, NewStr: string; StartIndex, Count: Integer指定範圍內替換字串

完整實作程式碼


procedure TForm1.Button1Click(Sender: TObject); // 字串全域替換
var sb: TStringBuilder;
begin
  sb := TStringBuilder.Create;
  try
    sb.Append('從 Delphi 2007 到 Delphi 2009');
    sb.Replace('Delphi', 'CBuilder');
    ShowMessage(sb.ToString); // '從 CBuilder 2007 到 CBuilder 2009'
  finally sb.Free; end;
end;

procedure TForm1.Button2Click(Sender: TObject); // 字元全域替換
var sb: TStringBuilder;
begin
  sb := TStringBuilder.Create;
  try
    sb.Append('從 Delphi 2007 到 Delphi 2009');
    sb.Replace('0', '9');
    ShowMessage(sb.ToString); // '從 Delphi 2997 到 Delphi 2999'
  finally sb.Free; end;
end;

procedure TForm1.Button3Click(Sender: TObject); // 字元區間替換
var sb: TStringBuilder;
begin
  sb := TStringBuilder.Create;
  try
    sb.Append('ABABABABABAB');
    // 從索引 4 開始,共 5 字元範圍內將 'A' 替換為 '-'
    sb.Replace('A', '-', 4, 5);
    ShowMessage(sb.ToString); // 'ABAB-B-B-BAB'
  finally sb.Free; end;
end;

procedure TForm1.Button4Click(Sender: TObject); // 字串區間替換
var sb: TStringBuilder;
begin
  sb := TStringBuilder.Create;
  try
    sb.Append('ABC123ABC123ABC123');
    // 從索引 3 開始,共 12 字元範圍內將 'ABC' 替換為 '-'
    sb.Replace('ABC', '-', 3, 12);
    ShowMessage(sb.ToString); // 'ABC123-123-123'
  finally sb.Free; end;
end;

參數詳解:StartIndex 與 Count

  • StartIndex:0-based 替換起始位置
  • Count:替換掃描範圍長度 (字元數)
  • 範例解析:'ABABABABABAB'.Replace('A', '-', 4, 5)
    • 索引 4='A',掃描 5 字元:索引 4,5,6,7,8 → 'A','B','A','B','A'
    • 範圍內 3 個 'A' 被替換為 '-' → 結果 'ABAB-B-B-BAB'
  • 字串區間:'ABC123ABC123ABC123'.Replace('ABC', '-', 3, 12)
    • 索引 3='1',掃描 12 字元:'123ABC123ABC'
    • 範圍內 2 個 'ABC' 被替換 → 'ABC123-123-123'

Replace vs StringReplace 效能對比

指標StringReplaceTStringBuilder.Replace優勢
記憶體分配每次產生新字串原地修改緩衝區無碎片、低 GC 壓力
多次替換累積分配開銷單一緩衝區操作線性擴容 vs 指數分配
區間替換需 Copy+Replace+Copy原生支援程式碼簡潔、效能高
鏈式操作需中間變數回傳 Self 可鏈式sb.Replace(...).Append(...)

進階應用場景

1. 模板引擎核心:批次佔位符替換


function RenderTemplate(const Template: string; const Params: TDictionary): string;
var
  sb: TStringBuilder;
  pair: TPair;
begin
  sb := TStringBuilder.Create(Template);
  try
    for pair in Params do
      sb.Replace('{' + pair.Key + '}', pair.Value); // 全域替換
    Result := sb.ToString;
  finally
    sb.Free;
  end;
end;

2. 敏感詞過濾:區間保護 (如程式碼區塊不替換)


function FilterSensitive(const Text: string; const SensitiveWords: array of string): string;
var
  sb: TStringBuilder;
  i, codeStart, codeEnd: Integer;
  word: string;
begin
  sb := TStringBuilder.Create(Text);
  try
    // 簡易:保護 `` `code` `` 區塊不被替換
    // 實際需狀態機解析
    for word in SensitiveWords do
      sb.Replace(word, StringOfChar('*', Length(word)));
    Result := sb.ToString;
  finally
    sb.Free;
  end;
end;

3. 格式化清理:移除多餘空白、統一換行


procedure NormalizeText(sb: TStringBuilder);
begin
  sb.Replace(#13#10, #10); // CRLF → LF
  sb.Replace(#13, #10);    // CR → LF
  sb.Replace(#9, '  ');    // Tab → 2 spaces
  // 多空白壓縮 (需迴圈或正則,Replace 不支援正則)
  while sb.ToString.Contains('  ') do
    sb.Replace('  ', ' ');
end;

4. 程式碼重構輔助:區間重命名變數


procedure RenameInRange(sb: TStringBuilder; const OldName, NewName: string; StartLine, EndLine: Integer);
var
  lineStart, lineEnd, charStart, charCount: Integer;
begin
  // 將行號轉換為字元索引 (簡化版)
  charStart := LineToCharIndex(sb, StartLine);
  charCount := LineToCharIndex(sb, EndLine + 1) - charStart;
  sb.Replace(OldName, NewName, charStart, charCount);
end;

內部實作原理 (簡化)


// 字串替換核心邏輯
function TStringBuilder.ReplaceInternal(const OldStr, NewStr: string; StartIndex, Count: Integer): TStringBuilder;
var
  oldLen, newLen, diff, i, found: Integer;
  p: PChar;
begin
  oldLen := Length(OldStr);
  newLen := Length(NewStr);
  diff := newLen - oldLen;

  i := StartIndex;
  while i <= StartIndex + Count - oldLen do
  begin
    // 尋找匹配 (簡化: 實際用優化搜尋演算法)
    found := FindSubstring(OldStr, i);
    if found < 0 then Break;
    if found > StartIndex + Count - oldLen then Break;

    // 計算位移
    if diff <> 0 then
    begin
      EnsureCapacity(Length + diff);
      Move(FData[found + oldLen], FData[found + newLen], (Length - found - oldLen) * SizeOf(Char));
      Inc(FLength, diff);
      Inc(Count, diff); // 調整剩餘掃描範圍
    end;

    // 複入新字串
    Move(Pointer(NewStr)^, FData[found], newLen * SizeOf(Char));
    i := found + newLen; // 繼續下一個位置
  end;
  Result := Self;
end;

常見陷阱與避坑

陷阱後果正確做法
OldStr 為空字串無限迴圈/崩潰檢查 if OldStr = '' then Exit
區間參數誤解替換範圍錯誤Count 是「掃描字元數」,非替換次數
替換後長度變化影響索引後續邏輯索引錯亂用 Replace 回傳 Self 鏈式,或重新計算索引
大小寫敏感漏替換需自行實作不區分大小寫版本

最佳實務建議

  • 大量替換前 EnsureCapacity:預估最終長度避免多次擴容
  • 字元替換優於字串替換:單字元替換最快,簡單字元映射優先用 Char 版
  • 區間替換保護非目標區域:如程式碼區塊、字串字面值
  • 鏈式呼叫:sb.Replace('a','b').Replace('c','d').Append('end')
  • 需不區分大小寫時:轉大寫後替換,或用正則庫

總結

TStringBuilder.Replace 以四重載覆蓋字元/字串、全域/區間四大替換場景,內部原地緩衝區修改避免記憶體分配開銷。掌握 StartIndex/Count 區間語意、diff 長度差自動調整機制、鏈式呼叫模式,配合 EnsureCapacity 預分配,即能高效實現模板渲染、敏感詞過濾、格式化清理、程式碼重構等進階替換需求。

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