替换HTML字符串中的字符 - 除标记外

Guy*_*ush 4 html delphi string replace char

我需要通过HTML字符串并将字符替换为0(零),标签,空格和换行符除外.我在下面创建了这个代码,但它太慢了.请有人帮助我加快速度(优化)吗?

procedure TForm1.btn1Click(Sender: TObject);
var
  Txt: String;
  Idx: Integer;
  Tag: Boolean;
begin
  Tag := False;
  Txt := mem1.Text;
  For Idx := 0 to Length(Txt) - 1 Do
  Begin
    If (Txt[Idx] = '<') Then
      Tag := True Else
    If (Txt[Idx] = '>') Then
    Begin
      Tag := False;
      Continue;
    end;
    If Tag Then Continue;
    If (not (Txt[Idx] in [#10, #13, #32])) Then
      Txt[Idx] := '0';
  end;
  mem2.Text := Txt;
end;
Run Code Online (Sandbox Code Playgroud)

HTML文本永远不会有"<"或">"外部标记(在文本中间),所以我不需要担心这一点.

谢谢!

Mas*_*ler 7

这看起来非常简单.如果没有根据您正在使用的数据分析代码,很难确定(这总是一个好主意;如果您需要优化Delphi代码,请先尝试通过Sampling Profiler运行它,以了解您实际花费的地方你所有的时间,但如果我必须做出有根据的猜测,我猜你的瓶颈在这一行:

Txt[Idx] := '0';
Run Code Online (Sandbox Code Playgroud)

作为编译器保证类型的安全写时复制语义的一部分,对string字符串的单个元素(字符)的每次写入都涉及对UniqueString例程的隐藏调用.这可以确保您不会更改其他地方的其他地方包含引用的字符串.

在这种特殊情况下,这不是必需的,因为你在这个例程的开头就得到了新的字符串,你知道它是独一无二的.如果你小心的话,有办法解决它.

清晰和不可靠的警告:不要先确定你要解释的事情,而不要先确定你有一个独特的字符串! 完成此UniqueString操作的最简单方法是手动调用.此外,在循环期间不要做任何可以将此字符串分配给任何其他变量的操作.虽然我们这样做,但它并没有被视为正常的字符串. 不注意此警告可能会导致数据损坏.

好了,既然已经解释过,你可以使用指针直接访问字符串的字符,并绕过编译器的安全措施,如下所示:

procedure TForm1.btn1Click(Sender: TObject);
var
  Txt: String;
  Idx: Integer;
  Tag: Boolean;
  current: PChar; //pointer to a character
begin
  Tag := False;
  Txt := mem1.Text;
  UniqueString(txt); //very important
  if length(txt) = 0 then
    Exit; //If you don't check this, the next line will raise an AV on a blank string
  current := @txt[1];
  dec(current); //you need to start before element 1, but the compiler won't let you
                //assign to element 0
  For Idx := 0 to Length(Txt) - 1 Do
  Begin
    inc(current); //put this at the top of the loop, to handle Continue cases correctly
    If (current^ = '<') Then
      Tag := True Else
    If (current^ = '>') Then
    Begin
      Tag := False;
      Continue;
    end;
    If Tag Then Continue;
    If (not (current^ in [#10, #13, #32])) Then
      current^ := '0';
  end;
  mem2.Text := Txt;
end;
Run Code Online (Sandbox Code Playgroud)

这改变了这个比喻.我们不是将字符串作为数组索引,而是将其视为磁带,指针为头部,一次向前移动一个字符,从头到尾扫描,并在适当时更改其下的字符.没有冗余调用UniqueString,也没有重复计算偏移量,这意味着这可以快得多.

使用像这样的指针时要非常小心. 编译器的安全检查是有充分理由的,并且在它们之外使用指针步骤.但有时,它们确实可以帮助您加快代码速度.再试一次,在尝试这样的事情之前.确保你知道什么在减慢事情,而不是只是想你知道.如果结果是其他运行缓慢的东西,不要这样做; 找到真正问题的解决方案.