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

Delphi 2009 TStringBuilder 進階:Insert 與 Remove 字串插入刪除完全指南

     編輯:Delphi

動態字串編輯核心:Insert 與 Remove

TStringBuilder 提供 Insert 與 Remove 方法,支援在緩衝區任意位置進行字串插入與刪除,避免傳統字串拼接的大量記憶體分配與複製開銷。

核心 API

方法參數說明
InsertIndex: Integer; Value: string/Char/其他型別在 Index 位置插入值,後續字元後移
RemoveIndex: Integer; Count: Integer從 Index 刪除 Count 個字元

完整實作程式碼


procedure TForm1.Button1Click(Sender: TObject);
var
  sb: TStringBuilder;
begin
  sb := TStringBuilder.Create;
  try
    sb.Append('CodeGear 2007');
    // 在 'CodeGear ' (長度 9) 後插入 'Delphi '
    sb.Insert(Length('CodeGear '), 'Delphi ');
    ShowMessage(sb.ToString); // 'CodeGear Delphi 2007'

    // 刪除 ' 2007' (從 'CodeGear Delphi' 長度 14 開始,長度 5)
    sb.Remove(Length('CodeGear Delphi'), Length(' 2007'));
    ShowMessage(sb.ToString); // 'CodeGear Delphi'

    // 在末尾插入 ' 2009'
    sb.Insert(sb.Length, ' 2009');
    ShowMessage(sb.ToString); // 'CodeGear Delphi 2009'
  finally
    sb.Free;
  end;
end;

參數詳解與索引語意

Insert(Index, Value)

  • Index:0-based 插入位置。0 = 最前面,Length = 末尾 (等同 Append)
  • Value:支援 string、Char、數值型別、物件等 (內部轉字串)
  • 行為:原 Index 及之後字元右移,Length 增加 Length(Value)

Remove(Index, Count)

  • Index:0-based 刪除起始位置
  • Count:刪除字元數
  • 行為:Index+Count 之後字元左移填補,Length 減少 Count
  • 邊界:Index + Count <= Length,否則拋出例外

進階應用場景

1. 模板字串填充:佔位符替換


function FillTemplate(const Template: string; const Values: array of string): string;
var
  sb: TStringBuilder;
  i, pos: Integer;
  placeholder: string;
begin
  sb := TStringBuilder.Create(Template);
  try
    for i := 0 to High(Values) do
    begin
      placeholder := '{' + IntToStr(i) + '}';
      pos := sb.ToString.IndexOf(placeholder);
      if pos >= 0 then
      begin
        sb.Remove(pos, Length(placeholder));
        sb.Insert(pos, Values[i]);
      end;
    end;
    Result := sb.ToString;
  finally
    sb.Free;
  end;
end;

// 使用: FillTemplate('Hello {0}, welcome to {1}!', ['User', 'Delphi'])
// → 'Hello User, welcome to Delphi!'

2. 高效字串建構:預留位置後填充


procedure BuildReport(sb: TStringBuilder; const Sections: array of string);
const
  SEP = ' | ';
var
  i, pos: Integer;
begin
  // 預建結構: [Section0] | [Section1] | ...
  for i := 0 to High(Sections) do
  begin
    if i > 0 then sb.Append(SEP);
    pos := sb.Length; // 記錄插入點
    sb.Append('[Section' + IntToStr(i) + ']'); // 佔位符
    // 稍後填充真實內容
    sb.Remove(pos, Length('[Section' + IntToStr(i) + ']'));
    sb.Insert(pos, Sections[i]);
  end;
end;

3. 實作類 StringBuilder.ReplaceAll (全域替換)


procedure ReplaceAll(sb: TStringBuilder; const OldStr, NewStr: string);
var
  pos: Integer;
  oldLen: Integer;
begin
  oldLen := Length(OldStr);
  if oldLen = 0 then Exit;
  pos := 0;
  while True do
  begin
    pos := sb.ToString.IndexOf(OldStr, pos);
    if pos < 0 then Break;
    sb.Remove(pos, oldLen);
    sb.Insert(pos, NewStr);
    pos := pos + Length(NewStr); // 繼續搜尋替換後位置
  end;
end;

4. 緩衝區縮減:移除前後空白


procedure TrimInPlace(sb: TStringBuilder);
var
  start, finish: Integer;
begin
  // 找第一個非空白
  start := 0;
  while (start < sb.Length) and (sb.Chars[start] <= ' ') do Inc(start);
  // 找最後一個非空白
  finish := sb.Length - 1;
  while (finish >= 0) and (sb.Chars[finish] <= ' ') do Dec(finish);

  if start > 0 then sb.Remove(0, start);
  if finish < sb.Length - 1 then sb.Remove(finish + 1, sb.Length - finish - 1);
end;

Insert/Remove vs 字串操作效能對比

操作String (s := s + ...)TStringBuilder Insert/Remove優勢
中間插入O(n) 分配新字串 + 複製O(n) 緩衝區移動 (無新分配)避免記憶體碎片
中間刪除O(n) 分配新字串 + 複製O(n) 緩衝區移動同理
多次連續編輯指數級分配線性緩衝區擴容巨大優勢
最終 ToString已是字串單次分配輸出可控

內部實作原理 (簡化)


// Insert 核心邏輯
procedure TStringBuilder.Insert(Index: Integer; const Value: string);
var valLen: Integer;
begin
  valLen := Length(Value);
  EnsureCapacity(Length + valLen); // 確保容量
  // 移動現有資料騰出空間
  Move(FData[Index], FData[Index + valLen], (Length - Index) * SizeOf(Char));
  // 複入新值
  Move(Pointer(Value)^, FData[Index], valLen * SizeOf(Char));
  Inc(FLength, valLen);
end;

// Remove 核心邏輯
procedure TStringBuilder.Remove(Index, Count: Integer);
begin
  // 移動後續資料覆蓋刪除區段
  Move(FData[Index + Count], FData[Index], (Length - Index - Count) * SizeOf(Char));
  Dec(FLength, Count);
end;

常見陷阱與避坑

陷阱後果正確做法
Index 超出範圍EArgumentOutOfRangeException插入允許 Index=Length,刪除需 Index+Count ≤ Length
迴圈中 Insert 導致索引錯亂漏插/重複插入從後往前處理,或記錄位移量補償
Remove(0, Length) 清空可行但非慣用用 Length := 0 或 Clear
Insert 大量小字串頻繁擴容移動預分配 EnsureCapacity 或批次組裝

最佳實務建議

  • 大量編輯前預分配:sb.EnsureCapacity(預估最終長度)
  • 批次插入用 Append + 最後調整:而非多次 Insert
  • 替換操作用 Replace 方法:內部優化優於手動 Remove+Insert
  • 索引計算用 Length/Length():避免硬編碼魔術數字
  • 配合 Chars[] 進行字元級精細操作:單字元修改無移動開銷

總結

TStringBuilder.Insert 與 Remove 以緩衝區移動取代字串重新分配,為動態字串編輯提供 O(n) 且無記憶體碎片的高效方案。掌握 Index 0-based 語意、Count 範圍邊界、EnsureCapacity 預分配技巧,配合 Replace、Chars[] 等輔助方法,即能優雅實現模板填充、報表建構、原地修剪等進階編輯場景。

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