加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

如何将PChar的一部分提取到字符串中?

发布时间:2020-12-15 09:23:13 所属栏目:大数据 来源:网络整理
导读:在分析期间,我遇到了一个耗费了相当多时间的函数,但基本上归结为这段非常简单的代码: function GetSubstring(AInput: PChar; AStart,ASubstringLength: Integer): string;begin Result := Copy(AInput,AStart,ASubstringLength);end; 此函数返回预期的子字
在分析期间,我遇到了一个耗费了相当多时间的函数,但基本上归结为这段非常简单的代码:

function GetSubstring(AInput: PChar; AStart,ASubstringLength: Integer): string;
begin
  Result := Copy(AInput,AStart,ASubstringLength);
end;

此函数返回预期的子字符串,但对于较长的输入,它不能很好地扩展.我查看了CPU视图中的汇编代码,从我所知道的(我通常不在汇编程序级别工作),似乎在调用Copy之前将AInput隐式转换为字符串.

但是,由于此时字符串/字符数组的长度未知,转换代码必须遍历PChar的长度,直到找到空终止符.这可以解释较长输入的可怕缩放.

但是,由于调用者传入了PChar的长度,我最初认为可以将该方法转换为使用SetString.

function GetSubstring(AInput: PChar; AStart,ASubstringLength: Integer): string;
begin
  SetString(Result,AInput + AStart - 1,ASubstringLength);
end;

除了SetString工作从零开始(不是一个基于复制),复制在验证其输入方面似乎还有许多其他的小东西,并非所有这些都被记录(例如,任何起始值小于1)改为1).所以上面的天真实现并不总是像原始实现一样.

我的目标是尽可能复制Copy例程,因为这个函数是库的一部分,并且已被我的同事广泛使用.

我想知道以下实现是否实现了这一点,或者我是否需要了解Copy的任何其他警告.注意:FLength是AInput的实际长度,它来自该函数所属模块中的另一部分.我为此示例删除了其他部分.

function GetSubstring(AInput: PChar; AStart,ASubstringLength: Integer): string;
begin
  if (AInput = nil) then begin
    Result := '';
  end else begin
    if (AStart < 1) then begin
      AStart := 0;
    end else begin
      AStart := AStart - 1;
    end;
    if (ASubstringLength + AStart > FLength) then begin
      ASubstringLength := FLength - AStart;
    end;
    SetString(Result,AInput + AStart,ASubstringLength);
  end;
end;

我正在使用Delphi 2006,但我认为这与其他版本的产品(至少非Unicode版本)没有太大区别.

解决方法

让我们考虑角落案例.我认为他们是:

> AInput无效.
> AStart< 1.
> AStart> FLength.
> ASubstringLength< 0.
> ASubstringLength(AStart-1)> FLength.

在我看来,我们可以忽略案例1.应该在呼叫者身上提供有效的PChar.确实,你检查AInput<>在我看来,nil已经走得太远,因为nil不是一个有效的PChar.

其余的你已经覆盖2和5,但不是3和4.因此,如果用户提供的AStart值太大,那么你将读取字符串的结尾.同样,用户可以轻松提供负ASubstringLength.我认为您不需要任何人编写代码来检查这些案例,因为您显然非常称职.

现在,如果你真的关心最后一滴性能,你不应该检查这些情况.要求用户传递有效参数.在调试模式下,使用{$IFOPF D}或Assert可以检查输入.当然,如果这些论点来自外部来源,那么它们应该得到验证.

另一方面,原始代码遭受的最大性能损失是不必要的扫描整个字符串,并将复制到中间堆分配的字符串.一旦你删除了那些,就像你一样,那么进一步提高性能的机会就会大大减少.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读