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

个人连结

在分析过程中,我遇到了一个函数,该函数花了很多时间,但实际上归结为这段非常简单的代码:

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

此函数返回预期的子字符串,但对于较长的输入而言,缩放效果不佳。我在CPU视图中查看了汇编代码,据我所知(我通常不在汇编级别工作),似乎AInput在调用之前已隐式转换为字符串Copy

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

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

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

除了SetString基于零的工作(不是基于副本的工作)之外,Copy在验证其输入方面似乎还有很多其他小事情,但并未记录全部(例如,任何小于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版本)没有太大不同。

戴维·赫弗南

让我们考虑一些极端情况。我认为他们是:

  1. AInput 无效。
  2. AStart < 1
  3. AStart > FLength
  4. ASubstringLength < 0
  5. ASubstringLength + (AStart-1) > FLength

我认为我们可以忽略情况1。责任应由呼叫者提供有效PChar的确AInput <> nil,我认为您的支票已经nil无效,因为这是无效的PChar

在剩下的部分中,您介绍了2和5,但没有介绍3和4。因此,如果用户提供的值AStart太大,那么您将读取字符串的末尾。同样,用户可以轻松提供负片ASubstringLength我认为您显然很称职,因此您不需要任何人来编写代码来检查这些情况。

现在,如果您真的在乎性能的每一个下降,那么您就不应该检查这些情况。要求用户传递有效参数。在调试模式下,使用{$IFOPF D+}Assert可以检查输入。当然,如果这些论点来自外部,则应该对其进行验证。

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

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

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

如何将字符串的一部分捕获到向量中

如何将字符串的一部分存储到字典中

Golang-如何将XML文件的一部分提取为字符串?

如何将字符串的一部分更改为 JSX 元素?

如何将Tkinter变量打印为字符串的一部分?

如何将字符串的一部分转换为整数?

如何将字符串的一部分转换为斜体?

如何将查询结果显示为字符串的一部分?

JavaScript:如何将颜色更改为仅输入字段中字符串的一部分?

如何将字符串的一部分从列复制到熊猫的新列中

如何将字符串的一部分读取为较小的字符串

如何提取包含特殊字符的字符串的一部分(编号)

如何将 Python 字符串变量添加到 Python 中的 SQL 字符串变量的一部分?

如何在蜂巢中提取字符串的一部分

如何提取子字符串作为dplyr :: mutate管道的一部分

如何使用preg_match提取找到的字符串的一部分?

如何仅提取字符串的一部分

如何在RDD中提取一部分字符串?

如何只替换单词的一部分?从字符串中提取整数?

如何在javascript中提取字符串的一部分?

如何在RegEx中提取字符串的一部分

cmd:如何提取字符串的一部分?

如何使用斜杠约束提取字符串的一部分?

如何在python中提取一部分字符串?

从 PHP 中的字符串中提取地址的一部分

如何使用jq解析器提取json对象中的一部分字符串值

如何将Go结构的一部分定义为JSON字符串?