可以看出,测试的结果(效率)是: PosN_PosEx > PosN_StrPos > PosN_Pos >> GetNSubStringPos 。
我本来期望的是 PosN_StrPos 最厉害,但结果不是。估计是 PosEx 优化得比较厉害。
附代码:
Unit1.pas:
unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, DBTables;type TPosNFunc = function (N: Integer; const SubString,AString: String): Integer;type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private procedure Tests(const funcs: array of TPosNFunc; const funcnames: array of string; iStr: integer; loopcount: integer); public end;var Form1: TForm1;implementationuses StrUtils;{$R *.dfm}function GetNSubStringPos(N: Integer; SubString,AString: String): Integer;//返回第n个SubString在AString中出现的位置//如果没找到,返回-1var FindCount: Integer; Pos: Integer;begin Result := -1; Pos := 0; for FindCount := 1 to N do begin Inc(Pos); while MidStr(AString, Pos, Length(SubString)) <> SubString do begin if Length(AString) < Length(SubString) + Pos then Exit;//未找到 Inc(Pos); end; end; Result := Pos;end;function PosN_Pos(N: Integer; SubString, AString: String): Integer;var p: integer; nSub: integer; nSrc: integer;begin nSub := Length( SubString ); nSrc := Length( AString ); result := -nSub; while N>0 do begin p := Pos(SubString, AString); if p=0 then break; Dec( N ); Inc( result, p+nSub ); AString := Copy( AString, p+nSub+1, nSrc-nSub-p-1 ); Dec( nSrc, nSub+p ); end; if N>0 then result := -1;end;function PosN_PosEx(N: Integer; SubString,AString: String): Integer;var p: integer; nSub: integer;begin nSub := Length( SubString ); result := 0; p := 0; while N>0 do begin p := PosEx( SubString, AString, p+1 ); if p=0 then break; Dec( N ); result := p; Inc( p, nSub ); end; if N>0 then result := -1;end;function PosN_StrPos(N: Integer; SubString, AString: String): Integer;var pSub, pSrc, p: Pchar; nSub: integer;begin nSub := Length( SubString ); pSub := PChar(SubString); pSrc := PChar(AString); p := pSrc; while (N>0) do begin p := StrPos( p, pSub ); if (p=nil) then break; Inc( p, nSub ); Dec( N ); end; if (N=0) and (p<>nil) then result := p - pSrc else result := 0;end;const STR = 'function GetNSubStringPos(N: Integer; SubString,AString: String): Integer;'; SUBSTR = 'String'; TEST_COUNT = 5;procedure TForm1.Tests( const funcs: array of TPosNFunc; const funcnames: array of string; iStr: integer; loopcount: integer );var i, j, k: Integer; tm: Longword; func: TPosNFunc; count: integer; retv: array of integer; results: array of Longword;begin count := Length(funcs); assert( count=Length(funcnames) ); Memo1.Lines.Add( Format('substr index: %d; LOOP COUNT = %d', [iStr, loopCount]) ); SetLength( retv, count ); SetLength( results, count ); for j:=0 to count-1 do results[j] := 0; for k:=1 to TEST_COUNT do begin for j:=0 to count-1 do begin func := funcs[j]; tm := GetTickCount; for i:=1 to loopcount do retv[j] := func( iStr, SUBSTR, str ); Inc( results[j], GetTickCount - tm ); end; end; for j:=0 to count-1 do begin Memo1.Lines.Add( Format( '%s: return %d; Timing: %n ms', [funcnames[j], retv[j], results[j]*1.0/TEST_COUNT ] ) ); end;end;procedure TForm1.Button1Click(Sender: TObject);var i: integer;begin for i:=1 to 4 do begin Memo1.Lines.Add( Format( '%d:', [i]) ); Tests( [@GetNSubStringPos], ['GetNSubStringPos'], i, 1000 ); Tests( [@PosN_Pos, @PosN_PosEx, @PosN_StrPos], ['PosN_Pos', 'PosN_PosEx', 'PosN_StrPos'], i, 100000 ); end;end;procedure TForm1.FormCreate(Sender: TObject);begin Memo1.Clear; Memo1.Lines.Add( Format( 'Search "%s" for "%s"', [STR, SUBSTR] ) );end;end.
Unit1.dfm:
object Form1: TForm1 Left = 243 Top = 164 Width = 578 Height = 516 AlphaBlendValue = 192 Caption = 'Form1' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False Position = poDefaultPosOnly OnCreate = FormCreate DesignSize = ( 570 489) PixelsPerInch = 96 TextHeight = 13 object Memo1: TMemo Left = 3 Top = 32 Width = 565 Height = 457 Anchors = [akLeft, akTop, akRight, akBottom] Lines.Strings = ( 'Memo1') ScrollBars = ssVertical TabOrder = 0 end object Button1: TButton Left = 3 Top = 6 Width = 75 Height = 25 Caption = 'Button1' TabOrder = 1 OnClick = Button1Click endend
……