Inno setup Pascal脚本计数一个字符串在另一个字符串中出现的次数

Inno setup Pascal脚本计数一个字符串在另一个字符串中出现的次数,inno-setup,pascalscript,Inno Setup,Pascalscript,我想计算一个字符串在Pascal脚本中的另一个字符串中出现的次数,如下面的示例所示 我已经看到了的答案,但是Pascal脚本中没有PosEx函数 MyString:='Hello World!,你好,世界!,你好,世界!,世界你好; 如果我计算这里出现Hello或World的次数,结果应该是4 如果我计算,(逗号)在这里出现的次数,结果应该是3 更新 下面的函数可以工作,但它会将给定的字符串再次复制到一个新变量,并删除部分字符串,因此工作速度较慢 函数发生子字符串(S,SubStr:Strin

我想计算一个字符串在Pascal脚本中的另一个字符串中出现的次数,如下面的示例所示

我已经看到了的答案,但是Pascal脚本中没有
PosEx
函数

MyString:='Hello World!,你好,世界!,你好,世界!,世界你好;
如果我计算这里出现
Hello
World
的次数,结果应该是4

如果我计算
(逗号)在这里出现的次数,结果应该是3

更新

下面的函数可以工作,但它会将给定的字符串再次复制到一个新变量,并删除部分字符串,因此工作速度较慢

函数发生子字符串(S,SubStr:String):整数;
变量
DSStr:字符串;
开始
如果Pos(SubStr,S)=0,则
出口
其他的
DSStr:=S;
重复
如果位置(子站,S)为0,则
公司(结果);
删除(DSStr,Pos(SubStr,DSStr),长度(复制(DSStr,Pos(SubStr,DSStr),长度(SubStr));
直到Pos(SubStr,DSStr)=0;
结束;

您的实现通常是正确的

需要进行一些优化,并删除无用的代码:

  • 如果Pos(SubStr,S)0(在
    repeat
    中)的第二个测试是没有意义的。总是这样。您正在测试
    S
    ,它已经在函数启动时测试过了。而
    DSStr
    已经在
    中进行了测试,直到
  • 您应该将Pos(SubStr,DSStr)保存到一个变量中,以避免多次调用它
  • Length(复制(DSStr,Pos(SubStr,DSStr),Length(SubStr))
    实际上与
    Length(SubStr)
    相同
  • 无需将
    S
    复制到
    DSStr
    。您可以直接使用
    S
    。它是按值参数,因此您不需要修改用于调用函数的变量
  • 将初始的
    Pos(SubStr,S)=0
    检查替换为循环中相同的检查,以保存一个
    Pos
    调用
代码的优化版本:

函数发生子字符串(S,SubStr:String):整数;
变量
P:整数;
开始
结果:=0;
重复
P:=Pos(SubStr,S);
如果P>0,则
开始
公司(结果);
删除(S、P、长度(SubStr));
结束;
直到P=0;
结束;

但实际上,使用Inno设置(Delphi没有),您不必自己编写任何算法

函数发生子字符串(S,SubStr:String):整数;
开始
结果:=StringChange(S,SubStr,);
结束;
这是受to的启发

虽然使用
StringChange
看起来效率低下(因为它有明显的副作用),但实际上速度更快。可能是因为它是用Pascal实现的,而不是用Pascal脚本实现的

测试了300万个呼叫:

发生子字符串('Hello World!、Hello World!、Hello World!、Hello World!'、'Hello')
  • 使用
    StringChange
    :11秒
  • 我的代码优化版本:49秒
  • 您的原始代码:99秒

尽管调用很少,但所有实现都足够好。

这不是一个代码编写服务。你自己做过任何努力吗?你可以不用PosEx;在PosEx出现之前已经做了几十年了。是的,我做了,但无法发布我的代码,因为它没有像我预期的那样工作。然后发布你的代码,并询问有关该代码的特定问题。再说一遍,这不是一个代码编写服务,在这里你发布你的需求和选择的语言,然后有人为你编写代码。好的,我会很快编辑我的问题-(非常好!谢谢你的编辑。:-)谢谢!作品由于时间不够,我用我的功能更新问题时迟到了-(感谢您的帮助!如果我直接使用
S
,调用您优化的函数版本后,
S
的内容不是会丢失吗?您所说的值是什么意思?如果您将参数声明为
S:string
,它将按值传递(按副本传递),因此对函数中
S
的任何修改都是在字符串的副本上进行的,不会影响用于调用函数的变量。请注意,也可以使用常量字符串调用此类函数。-与声明为
var S:string
的参数相反-这是通过引用传递的。对
S的任何修改de>将修改用于调用函数的变量-因此,您不能为参数使用常量字符串,因为该常量无法修改。另请参阅和。