现在流行写心得, 俺也来一篇。 如何高效地操作字符串。 给初学者一点帮助。 (鲜花和板砖都欢迎)(0分)

  • 主题发起人 主题发起人 Another_eYes
  • 开始时间 开始时间
我用这种办法暂时就可以了,但不知道效率会不会降下来
var
ts, TempStr: string;
n : integer;
begin
...
ts := string(@TempStr[n]);
SetLength(ts, StrLen - n);
m := pos('@', ts);
//从当前指针位置开始找分类部分
...
end;
 
String不是PChar。
 
to barton
我在我的电脑上试了一下,你这两种的速度基本一样,循环3000次
1、31毫秒
2、30毫秒
 
感谢soul。 实际情况的确如此。 当初写的时候,原本这句是这样的:
n := pos(SubStr, pchar(@Source));
后来觉得这样查找效率不高(因为delphi会生成代码每次查找pchar的length( REPNZ SCASB ), 如果source很长的话这句很浪费时间)。
测试的时候试了一下直接用string(@Source), 发觉没有问题, 所以就贴出来了。
考虑不周请大家原谅。
呵呵, 当初主要觉得第二种方法太难看, 所以想找种看得过去又比较高效的方法。
现在看来只有第二种方法才能达到比较高效处理字符串的目的了。
就我个人来说,我还是比较喜欢第三篇中查找字符串的方法(尽管还不是最高效的)。我不太愿意写纯汇编代码,因为调试太麻烦。
 
对我帮助很大!谢谢![:)]
 
有没有人想过使用“BM”算法来实现字符串地查找???
 
作者提供的算法大有问题:
Source := copy(Source, pos(SubStr, Source)+Length(SubStr), $7FFFFFFF);

if (Source=SubStr[1])
and CompareMem(@(Source), Pointer(SubStr), len1) then

是所谓效率的关键地方,第一个函数用了串拷贝,而第二个函数直接采用 PChar
串比较,无论从空间还是时间,都已经不是在同一个级别上作比较。因此效率的
说法是不存在的。
如果第一个函数提供
function CountSubStr(const SubStr, Source: PChar): Integer;

的形式,或者将 PChar ptr = PChar(Source);
只须考虑正常的 C 串(NULL 串)
处理办法,进行 ptr = Source + offset 的标准指针运算,效率应该差别不是很大。

说明:没有测试,所以无法提供测试值。
 
ddev:
//第一个函数用了串拷贝,而第二个函数直接采用 PChar
//串比较,无论从空间还是时间,都已经不是在同一个级别上作比较。因此效率的
//说法是不存在的。
真有意思,我说飞机比自行车开的快,你说他们不是在同一个级别上的,不能比较。
那你选哪个?
soul:
你的分析很有道理。我来谈一谈对你留下的那个疑问的看法:
//pos不知道为何还基本正确
pos 默认传进来的字符串是 ShortString,他不会理会什么引用计数,只管长度字符
(传进来的第一个字符),因此 string(@Source) 传进去过后,虽然看起来好像是
从 Source 开始找,其实不然,Delphi 把这第一个字符作为 ShortString 的长度
字符,而从 Source[i+1] 开始查找。
那为什么结果基本上没有错呢?很显然,虽然每次都是少找了一个字符,但是除了第
一次以外,每一次查找都是从上一次匹配开始的,而两个匹配连续出现的机率是很小
的,因此即使漏掉了上一次匹配后面的一个字符,一般不会影响结果。

 
to beta:
你认为一个 C 例程和一个 Basic / Java 例程,
即使算法完全一样,那一个会更快些?
算法的改进与讨论,必须具有基本相同的条件,
如果在串分析时故意作一些乱七八糟的无效代码,
和一个正常的例程,就能说某一个算法快吗?
这与我提出的两个函数的差别是一样的道理:
如果提供 KMS 算法或者更为有效的算法,
可以说是算法上的改进,而现在第一个函数
提供了完全没有必要的拷贝例程,这也能够
作为一个基本的算法来考证?
 
to ddev:
您看来没搞懂我写这篇的目的吧? 我写这篇的目的是告诉大家如何选择一种更高效的算法来处理字符串,而避免使用常见的低效的算法。
>>而现在第一个函数提供了完全没有必要的拷贝例程,这也能够作为一个基本的算法来考证?
您认为第一种不是一种基本的算法吗? 那么请问您心目中的算法如何定义呢?
我认为所谓算法就是如何组织程序代码以实现目的的方法。 只要能达到目的的都是算法。
而且delphi本身源代码中就大量使用本文第一个例程中的方法处理字符串的。 您能说这不是一个普通算法吗?
 
确切的说效率来自于对事物本身实质的理解。
上面两种算法,一种只认识到了语言层。也许在任何系统下都正确。
一种认识到了机器表现层,所以可以跳过语言的束缚而写出更直接的代码。
但是假如字符串可以大于4G那么他也许是个链表,于是第一种算法也许正选。
第二种算法成了一个错误,其实这就是说第二种算法暗含一个条件:字符串
必须顺序存储在内存中。而起copy真的是在复制字符串。
所以第二中方法很难看。但很透彻,也很局限。如果我们改造copy的构造和
语法,使之成为只是一个指针操作,而字符串长度和计数放在其他地方,那么
情况又不一样了。
 
学习!
关注!
 
看了半天,发觉delphi似乎没有提供操作string类型的Pos函数?
 
错了, delphi提供了string类型的Pos函数, 就是LStrPos. 它的循环控制次数取的就是offset -4偏移处的字符串长度。
 
学习&收藏!Thanks
 
// delphi似乎没有提供操作string类型的Pos函数
呵呵,刚才跟了一下,原来是编译器搞鬼。他自动判断要是传进去的是长字符串,则自动
给我们替换成了 _LStrPos :(
我就是纳闷了,明明传了个长字符串过去,就凭 _Pos 那个 MOV CL,[EDI] 取一个字节的
字符串长度,怎么能从超过 255 字节的字符串末尾找到匹配字符串。原来是编译器使坏,
呵呵。看一下 _LStrPos 前面那个 L 应该明白的:)
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部