字符串替换函数(速度极度超越delphi自带的stringReplace)

//字符串替换函数
//作者 QQ 287412388
//本代码,可以随意拷贝,修改使用,如果发现问题,请通知我.
//2011-09-09 14:18

function _stringReplace_(const Src,OldStr,NewStr:string):string;

const
  DEFAULT_LIST_BUFF_SIZE = 2048;

type
  PDataList=^TDataList;
  TDataList=record
    Buff:Pointer;
    Len:Integer;
    Next:PDataList;
    Position:Integer;
    //索引范围
    Start:Integer;
    Tail:Integer;
  end;

  PDataNode=^TDataNode;
  TDataNode=record
    Position:Integer;
    Len:Integer;
    BegPos:Integer;
    NewPos:Integer;
  end;

var
  Node,Header:PDataList;
  NewStr_Size,OldStr_Size:Integer;

  function NewDataNode(Len:Integer=4096):PDataList;
  begin
    New(Result);
    GetMem(Result^.Buff,Len);
    Result^.Len := Len;
    Result^.Next := nil;
    Result^.Position := 0;
  end;

  procedure FreeDataList(Data:pDataList);
  var
    TmpNode,Node:pDataList;
  begin
    Node := Data;
    while(Node <> nil) do
    begin
      FreeMem(Node^.Buff);
      TmpNode := Node;
      Node := Node.Next;
      Dispose(TmpNode);
    end;
  end;

  procedure AddData(Value:Integer);
  var
    P:PInteger;
  begin
    if Node^.Position = DEFAULT_LIST_BUFF_SIZE then
    begin
      Node.Next := NewDataNode(DEFAULT_LIST_BUFF_SIZE * 4);
      Node := Node.Next;
      ZeroMemory(Node^.Buff,Node^.Len);
    end;
    P := PInteger(Node^.Buff);
    Inc(P,Node^.Position);
    P^ := Value;
    Inc(Node^.Position);
  end;

  function getDataNode(Index:Integer;var Ref:Pointer):Integer;
  var
    ANode:PDataList;
    PI:PInteger;
  begin
    Result := 0;
    if Ref <> nil then
      ANode := Ref
    else
      ANode := Header;
    while(ANode <> nil) do
    begin
      if (Index>=ANode.Start) and (Index<=ANode.Tail) then
      begin
        PI := PInteger(ANode.Buff);
        Inc(PI,(Index- ANode.Start));
        Result := PI^;
        Ref := ANode;
        Break;
      end
      else ANode := ANode.Next;
    end;
  end;

  procedure getDataNode_II(Index:Integer;var P1,P2:Integer;var Ref:Pointer);
  var
    ANode:PDataList;
    PI:PInteger;
  begin
    if Ref <> nil then
      ANode := Ref
    else
      ANode := Header;
    while(ANode <> nil) do
    begin
      if (Index>=ANode.Start) and (Index<=ANode.Tail) then
      begin
        PI := PInteger(ANode.Buff);
        Inc(PI,(Index - ANode.Start));
        P1 := PI^;
        if (Index+1)<=ANode.Tail then
        begin
          Inc(PI);
          P2 := PI^;
          Ref := ANode;
          Exit;
        end;
        Break;
      end
      else ANode := ANode.Next;
    end;
    P2 := getDataNode(Index + 1,Ref);
  end;


  procedure FillDataNode(Index:Integer;PNode:PDataNode;var Ref:Pointer);
  var
    Position,NextPosition:Integer;
  begin
    getDataNode_II(Index,Position,NextPosition,Ref);
    PNode^.Len      := NextPosition - Position - OldStr_Size;
    PNode^.BegPos   := Position + OldStr_Size;
    PNode^.Position := Position;
    PNode^.NewPos   := Position;
  end;

  procedure InternalCopyMemory(PD,PS:PChar;len:Integer);
  begin
    if Len = 0 then
      Exit;
    case Len of
        1: PD^ := PS^;
        2: PWORD(PD)^ := DWORD(PS^);
        3: begin
             PD^ := PS^;
             (PD+1)^ := (PS+1)^;
             (PD+2)^ := (PS+2)^;
           end;
        4: PInteger(PD)^ := PInteger(PS)^;
     else
        CopyMemory(PD,PS,Len);
    end;
     //\\
  end;

  procedure WriteDataII(PD:PChar;AReplaceCount:Integer);
  var
    PS:PChar;
    Index:Integer;
    P1:PDataNode;
    NodeRef:Pointer;
    //\\
    TmpInt:Integer;
  begin
    NodeRef := nil;
    New(P1);
    for Index := 0 to AReplaceCount - 1 do
    begin
      if Index = 0 then
      begin
        TmpInt := getDataNode(Index+1,NodeRef);
        P1^.Position := 1;
        P1^.BegPos   := 1;
        P1^.Len      := TmpInt - 1;
        P1^.NewPos   := TmpInt;
      end
      else
        FillDataNode(Index,P1,NodeRef);

      if Index > 0 then
      begin
        if P1^.BegPos < P1^.NewPos then
        begin
          if P1^.Len > 0 then
          begin
            PS := Pointer(Src);
            Inc(PS,P1^.BegPos - 1);
            InternalCopyMemory(PD,PS,P1^.Len);
            Inc(PD,P1^.Len);
          end;
          if NewStr_Size > 0 then
          begin
            InternalCopyMemory(PD,Pointer(NewStr),NewStr_Size);
            Inc(PD,NewStr_Size);
          end;
        end
        else begin
          if NewStr_Size > 0 then
          begin
            InternalCopyMemory(PD,Pointer(NewStr),NewStr_Size);
            Inc(PD,NewStr_Size);
          end;
          if P1^.Len > 0 then
          begin
            PS := Pointer(Src);
            Inc(PS,P1^.BegPos - 1);
            InternalCopyMemory(PD,PS,P1^.Len);
            Inc(PD,P1^.Len);
          end;
        end;
      end
      else begin
        if P1^.Len > 0 then
        begin
          PS := Pointer(Src);
          Inc(PS,P1^.BegPos - 1);
          InternalCopyMemory(PD,PS,P1^.Len);
          Inc(PD,P1^.Len);
        end;
      end;
    end;//for end
  Dispose(P1);
end;

 


var
  OffSet,OutSize:Integer;
    ReplaceCount:Integer;
  PD:PChar;
  Index:Integer;
begin
  OffSet := 1;

  NewStr_Size := Length(NewStr);
  OldStr_Size := Length(OldStr);

  Header := NewDataNode(DEFAULT_LIST_BUFF_SIZE * 4);
  ZeroMemory(Header^.Buff,Header^.Len);
  Node := Header;

  AddData(1);//前插
  ReplaceCount := 0;
  while(true) do
  begin
    OffSet := PosEx(OldStr,Src,OffSet);
    if OffSet > 0 then
    begin
      AddData(OffSet);
      Inc(ReplaceCount);
      Inc(OffSet);
    end
    else begin
      AddData(Length(Src) + 1);
      Break;
    end;
  end;

  Index := 0;
  Node := Header;
  while(Node <> nil) do
  begin
    Node.Start := Index;
    Node.Tail  := Index + DEFAULT_LIST_BUFF_SIZE -1;
    Index := Node.Tail + 1;
    Node  := Node.Next;
  end;

  //计算输出字符的长度
  if ReplaceCount = 0 then
  begin
    Result := Src;
    Exit;
  end;


  //分配输出缓冲区
  OutSize := Length(Src) - OldStr_Size * ReplaceCount;
  OutSize := OutSize + NewStr_Size * ReplaceCount;
  SetLength(Result,OutSize);


  //复制数据到输出缓冲区
  PD := Pointer(Result);
  WriteDataII(PD,ReplaceCount + 1);//-1 删除掉最后一条不计算

  //释放内存块
  FreeDataList(Header);
  //\\
end;


//测试代码,仅供参考
procedure TForm1.Button1Click(Sender: TObject);
var
  TmpStr:string;
  FS:TFileStream;
  D:DWORD;
  I:Integer;
begin
  D := getTickCount();
  for I := 1 to 1000 do
    TmpStr := _stringReplace_(src,'A','a');

  D := GetTickCount() - D;
  ShowMessage(IntToStr(D));


  FS := TFileStream.Create('E:\Text.TXT',fmCreate);
  FS.Write(TmpStr[1],Length(TmpStr));
  FS.Free();

 // getMem(PS,1024);
end;


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值