Delphi实验:在串中查找第i个子串的位置及效率评测[1]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 agui 的 blog

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函数。

程序输出:

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;
interface
uses
  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;
implementation
uses
  strutils;
{$r *.dfm}
function getnsubstringpos(n: integer; substring,astring: string): integer;
//返回第n个substring在astring中出现的位置
//如果没找到,返回-1
var
  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

本文关键:Delphi实验:在串中查找第i个子串的位置及效率评测
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top