字符串替换,速度成问题,各位老大帮忙看看,300分不成敬意(300分)

  • 主题发起人 主题发起人 Derlin
  • 开始时间 开始时间
可以用俄罗斯人 Andrew N. Driazgov 写的 QStrings 字符串处理库操作字符串,效率很高。
 
彼得-莫里斯的那两个单元好象在DELPHI INFORMATION上发表过
 
原来转换方法有这么多啊,学到东西了!
就楼主的函数来讨论,我觉得有几点需要改进的地方:
1)如果字串存在[[Tstr1[[Tstr2]]]]就可能出错了。
2)程序中的 i := Pos('[[',tStr);和 j := Pos(']]',tStr);用得太频了,而且每个都
得扫描整个字串,建议设一个中间字串,分段保存替换结果,这样就确保整个字串仅
扫描一次就完成替换。效率会提高很多的。
 
同意楼上的, 设置中间字符串
 
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.
 
多人接受答案了。
 

Similar threads

I
回复
0
查看
853
import
I
I
回复
0
查看
776
import
I
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
后退
顶部