专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Delphi教程 » 字符串查找:在串中查找第i个子串的位置及效率评测 »正文

字符串查找:在串中查找第i个子串的位置及效率评测

来源: 发布时间:星期三, 2008年9月24日 浏览:116次 评论:0

lw549说 取得字符串中指定子字符串出现第n次的位置,效率不高,勉强可用 。感上兴趣,于是试上一试。
程序附在最后,这里是一些说明文字:
1、为快速写好,没有使用应当使用的控制台方式,而是使用了GUI方式;
2、测试的样例是查找包含有四处子串的字符串,四次分别查四个位置。这个在Button1Click方法中完成,它调用Tests来进行具体测试,以被测函数、第几次出现、循环次数为参数;
3、Tests依次在一个循环中重复调用每个具体的函数,同时为了公平起见(也许前面的函数为后面的铺了一些路——内存、高速缓冲),这样的测试进行TEST_COUNT次,最后输出每次的平均时间;
4、经过前期的测试,lw549 的代码的确效率不高,所以单独给它小一些的循环次数(一千次),以免造成程序假死现象;其它的为十万次;
5、其它三个函数的思想为:
PosN_Pos: 使用Pos函数及Copy函数;
PosN_PosEx: 使用Delphi 7中增加的PosEx函数;
PosN_StrPos: 使用StrPos函数。

程序输出:

参考:[http://www.CrazyCoder.cn/]Search \"function GetNSubStringPos(N: Integer; SubString,AString: String): Integer;\" for \"String\"
1:
substr index: 1; LOOP COUNT = 1000
GetNSubStringPos: return 17; Timing: 37.60 ms
substr index: 1; LOOP COUNT = 100000
PosN_Pos: return 17; Timing: 40.40 ms
PosN_PosEx: return 17; Timing: 15.60 ms
PosN_StrPos: return 22; Timing: 37.80 ms
2:
substr index: 2; LOOP COUNT = 1000
GetNSubStringPos: return 42; Timing: 96.80 ms
substr index: 2; LOOP COUNT = 100000
PosN_Pos: return 42; Timing: 81.20 ms
PosN_PosEx: return 42; Timing: 47.00 ms
PosN_StrPos: return 47; Timing: 53.00 ms
3:
substr index: 3; LOOP COUNT = 1000
GetNSubStringPos: return 50; Timing: 109.40 ms
substr index: 3; LOOP COUNT = 100000
PosN_Pos: return 50; Timing: 118.80 ms
PosN_PosEx: return 50; Timing: 53.00 ms
PosN_StrPos: return 55; Timing: 62.60 ms
4:
substr index: 4; LOOP COUNT = 1000
GetNSubStringPos: return 58; Timing: 128.20 ms
substr index: 4; LOOP COUNT = 100000
PosN_Pos: return 58; Timing: 162.60 ms
PosN_PosEx: return 58; Timing: 59.40 ms
PosN_StrPos: return 63; Timing: 74.80 ms

可以看出,测试的结果(效率)是: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.

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: