TransStr ->你的算法
TransStr2 ->使用PosEx/利用StrList保存中间数据
TransStr3 ->对TransStr2优化 在合并最后结果时采用内存拷贝而不是不断更改结果字符串
TransStr4 ->对源字符串中不需要替换的地方采用指针标记,需要替换的地方仍然是拷贝
TransStr5 ->对所有的字符段均采用指针标记
对于很简单的字符串 很多个'Edit0[[abd]]def'重复 测试TransStr3效能最好(TransStr3比TransStr2性能好很多这说明减少字符串的创建可以比较明显的提高性能),至于其他的算法,因为没有合适的输入数据,所以结果和理论有所差别
至于TransStr4/TransStr5,只用于源字符串中每个段比较长的时候,因为在减少内存拷贝的同时这里需要不断分配记录。(因为这两个结构比较简单,所以可以通过Array/TList模拟,通过设置较大的TList.Cap?来降低分配记录的时间消耗,从而获得理论上比TransStr3更好的性能)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Edit0: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses StrUtils;
function TransStr(tStr: string): string;
var
i,j : Integer;
Value, tStr2 : string;
begin
i := Pos('[[',tStr);
j := Pos(']]',tStr);
while (i > 0) and (j > 0) do
begin
tStr2 := Copy(tStr,i,j-i+2);
Value := Copy(tStr,i+2,j-i-2);
Value := '<a href="http://www.derlin.net/' + Value + '">' + Value + '</a>';
tStr := StringReplace(tStr,tStr2,Value,[rfReplaceAll]);
i := Pos('[[',tStr);
j := Pos(']]',tStr);
end;
Result := tStr;
end;
function TransStr2(SrcStr: string): string;
var
aInt, bInt: Integer;
Value: string;
StrList: TStringList;
begin
StrList:= TStringList.Create
Result:= '';
bInt:= 1;
aInt:= PosEx('[[', SrcStr, bInt);
while (aInt>0) do
begin
StrList.Add(Copy(SrcStr, bInt, aInt-bInt));
bInt:= PosEx(']]', SrcStr, aInt+2);
if (bInt>0) then
begin
Value:= Copy(SrcStr, aInt+2, bInt-aInt-2);
StrList.Add('<a href="http://www.derlin.net/' + Value + '">' + Value + '</a>');
Inc(bInt, 2);
aInt:= PosEx('[[', SrcStr, bInt);
end
else
begin
StrList.Add(Copy(SrcStr, aInt, MaxInt));
aInt:= 0;
bInt:= MaxInt;
end;
end;
if bInt<Length(SrcStr) then
begin
Value:= Copy(SrcStr, bInt, MaxInt);
StrList.Add(Value);
end;
Result:= '';
for aInt:=0 to StrList.Count-1 do
Result:= Result + StrList[aInt];
StrList.Free;
end;
function TransStr3(SrcStr: string): string;
var
aInt, bInt: Integer;
Value: string;
StrList: TStringList;
aLen: Integer;
ptr: PChar;
begin
StrList:= TStringList.Create
Result:= '';
aLen:= 0;
bInt:= 1;
aInt:= PosEx('[[', SrcStr, bInt);
while (aInt>0) do
begin
StrList.Add(Copy(SrcStr, bInt, aInt-bInt))
Inc(aLen, aInt - bInt);
bInt:= PosEx(']]', SrcStr, aInt+2);
if (bInt>0) then
begin
Value:= Copy(SrcStr, aInt+2, bInt-aInt-2);
Value:= '<a href="http://www.derlin.net/' + Value + '">' + Value + '</a>';
StrList.Add(Value)
Inc(aLen, Length(Value));
Inc(bInt, 2);
aInt:= PosEx('[[', SrcStr, bInt);
end
else
begin
StrList.Add(Copy(SrcStr, aInt, MaxInt))
Inc(aLen, Length(SrcStr) - aInt+1);
aInt:= 0;
bInt:= MaxInt;
end;
end;
if bInt<Length(SrcStr) then
begin
Value:= Copy(SrcStr, bInt, MaxInt);
StrList.Add(Value);
Inc(aLen, Length(Value));
end;
SetLength(Result, aLen);
ptr:= PChar(Result);
for aInt:=0 to StrList.Count-1 do
begin
Value:= StrList[aInt];
StrPCopy(ptr, Value);
Inc(ptr, Length(Value));
end;
StrList.Free;
end;
function TransStr4(SrcStr: string): string;
type
TBufRec = record
ptr: PChar;
Len: Integer;
end;
PBufRec = ^TBufRec;
var
BufList: TList;
pBuf: PBufRec;
ValList: TStringList;
aInt, bInt: Integer;
aLen: Integer;
Value: string;
ptr: PChar;
begin
BufList:= TList.Create;
ValList:= TStringList.Create;
aLen:= 0;
bInt:=1;
aInt:=PosEx('[[', SrcStr, bInt);
while(aInt>0) do
begin
new(pBuf);
pBuf.ptr:= PChar(DWORD(PChar(SrcStr))+bInt-1);
pBuf.Len:= aInt - bInt;
BufList.Add(pBuf)
Inc(aLen, pBuf.Len);
Inc(aInt, 2);
bInt:= PosEx(']]', SrcStr, aInt);
if bInt>0 then
begin
Value:= Copy(SrcStr, aInt, bInt-aInt);
Value:= '<a href="http://www.derlin.net/' + Value + '">' + Value + '</a>';
ValList.Add(Value);
new(pBuf);
pBuf.ptr:= PChar(Value);
pBuf.Len:= Length(Value);
BufList.Add(pBuf)
Inc(aLen, pBuf.Len);
Inc(bInt, 2);
aInt:= PosEx('[[', SrcStr, bInt);
end
else
begin
new(pBuf);
pBuf.ptr:= PChar(DWORD(PChar(SrcStr))+aInt-3);
pBuf.Len:= Length(SrcStr) - aInt +3;
BufList.Add(pBuf)
Inc(aLen, pBuf.Len);
aInt:= 0
bInt:= MaxInt;
end;
end;
if bInt<Length(SrcStr) then
begin
new(pBuf);
pBuf.ptr:= PChar(DWORD(PCHar(SrcStr)+bInt-1));
pBuf.Len:= Length(SrcStr)-bInt+1;
BufList.Add(pBuf)
Inc(aLen, pBuf.Len);
end;
SetLength(Result, aLen);
ptr:= PChar(Result);
for aInt:= 0 to BufList.Count-1 do
begin
pBuf:= BufList[aInt];
CopyMemory(ptr, pBuf.ptr, pBuf.Len);
Inc(ptr, pBuf.Len);
end;
ValList.Free;
for aInt:=BufList.Count-1 downto 0 do
begin
pBuf:= BufList[aInt];
Dispose(pBuf);
end;
BufList.Clear;
end;
function TransStr5(SrcStr: string): string;
type
TBufRec = record
flag: Integer
//0 -> 字符串 1- url value
ptr: PChar;
Len: Integer;
end;
PBufRec = ^TBufRec;
var
BufList: TList;
pBuf: PBufRec;
aInt, bInt: Integer;
aLen: Integer
ValCount: Integer
ValLen: Integer;
Value: string;
ptr: PChar;
begin
BufList:= TList.Create;
aLen:= 0
ValCount:= 0
ValLen:= 0;
bInt:=1;
aInt:=PosEx('[[', SrcStr, bInt);
while(aInt>0) do
begin
new(pBuf);
pBuf.flag:= 0;
pBuf.ptr:= PChar(DWORD(PChar(SrcStr))+bInt-1);
pBuf.Len:= aInt - bInt;
BufList.Add(pBuf)
Inc(aLen, pBuf.Len);
Inc(aInt, 2);
bInt:= PosEx(']]', SrcStr, aInt);
if bInt>0 then
begin
new(pBuf);
pBuf.flag:= 1;
pBuf.ptr:= PChar(DWORD(PChar(SrcStr))+aInt-1);
pBuf.Len:= bInt - aInt;
BufList.Add(pBuf)
Inc(ValCount)
Inc(ValLen, pBuf.Len);
Inc(bInt, 2);
aInt:= PosEx('[[', SrcStr, bInt);
end
else
begin
new(pBuf);
pBuf.flag:= 0;
pBuf.ptr:= PChar(DWORD(PChar(SrcStr))+aInt-3);
pBuf.Len:= Length(SrcStr) - aInt +3;
BufList.Add(pBuf)
Inc(aLen, pBuf.Len);
aInt:= 0
bInt:= MaxInt;
end;
end;
if bInt<Length(SrcStr) then
begin
new(pBuf);
pBuf.flag:= 0;
pBuf.ptr:= PChar(DWORD(PCHar(SrcStr)+bInt-1));
pBuf.Len:= Length(SrcStr)-bInt+1;
BufList.Add(pBuf)
Inc(aLen, pBuf.Len);
end;
SetLength(Result, aLen + ValLen*2 + ValCount * Length('<a href="http://www.derlin.net/'+ '">' + '</a>'));
ptr:= PChar(Result);
for aInt:= 0 to BufList.Count-1 do
begin
pBuf:= BufList[aInt];
if pBuf.flag = 0 then
begin
CopyMemory(ptr, pBuf.ptr, pBuf.Len);
Inc(pBuf);
end
else
begin //Length('<a href="http://www.derlin.net/') = 31;
CopyMemory(ptr, PChar('<a href="http://www.derlin.net/'), 31);
Inc(ptr, 31);
CopyMemory(ptr, pBuf.ptr, pBuf.Len);
Inc(ptr, pBuf.Len);
CopyMemory(ptr, PChar('">'), 2);
Inc(ptr, 2);
CopyMemory(ptr, pBuf.ptr, pBuf.Len);
Inc(ptr, pBuf.Len);
CopyMemory(ptr, PChar('</a>'), 4);
Inc(ptr, 4);
end;
end;
for aInt:=BufList.Count-1 downto 0 do
begin
pBuf:= BufList[aInt];
Dispose(pBuf);
end;
BufList.Clear;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
aInt, LoopCount: Integer;
Time1, Time2: TDateTime;
function GetTWStr: string;
begin
Result:= IntToStr(Round((Time2-Time1)*24*3600*1000));//ms
end;
begin
LoopCount:= 10000;
Time1:= Time;
for aInt:=LoopCount-1 downto 0 do
Edit1.Text:= TransStr(Edit0.Text);
Time2:= Time;
Label1.Caption:= GetTWStr;
Time1:= Time;
for aInt:=LoopCount-1 downto 0 do
Edit2.Text:= TransStr2(Edit0.Text);
Time2:= Time;
Label2.Caption:= GetTWStr;
Time1:= Time;
for aInt:=LoopCount-1 downto 0 do
Edit3.Text:= TransStr3(Edit0.Text);
Time2:= Time;
Label3.Caption:= GetTWStr;
Time1:= Time;
for aInt:=LoopCount-1 downto 0 do
Edit4.Text:= TransStr4(Edit0.Text);
Time2:= Time;
Label4.Caption:= GetTWStr;
Time1:= Time;
for aInt:=LoopCount-1 downto 0 do
Edit5.Text:= TransStr4(Edit0.Text);
Time2:= Time;
Label5.Caption:= GetTWStr;
end;
end.