delphi - 从字符串中删除所有非标准文本characers

IEl*_*ite 12 delphi parsing ascii delphi-7 delphi-2010

我需要从字符串中删除所有非标准文本characers.我需要删除所有非ascii和控制字符(换行/回车除外).

Dav*_*nan 20

而这里是Cosmin的一个变体,它只使用一次字符串,但使用了一种有效的分配模式:

function StrippedOfNonAscii(const s: string): string;
var
  i, Count: Integer;
begin
  SetLength(Result, Length(s));
  Count := 0;
  for i := 1 to Length(s) do begin
    if ((s[i] >= #32) and (s[i] <= #127)) or (s[i] in [#10, #13]) then begin
      inc(Count);
      Result[Count] := s[i];
    end;
  end;
  SetLength(Result, Count);
end;
Run Code Online (Sandbox Code Playgroud)

  • 非常好的变体,只有一次重新分配,如果字符串不包含 ani 非 ASCII 字符,则可能不会重新分配。 (2认同)

Jer*_*ers 13

这样的事情应该做:

// For those who need a disclaimer: 
// This code is meant as a sample to show you how the basic check for non-ASCII characters goes
// It will give low performance with long strings that are called often.
// Use a TStringBuilder, or SetLength & Integer loop index to optimize.
// If you need really optimized code, pass this on to the FastCode people.
function StripNonAsciiExceptCRLF(const Value: AnsiString): AnsiString;
var
  AnsiCh: AnsiChar;
begin
  for AnsiCh in Value do
    if (AnsiCh >= #32) and (AnsiCh <= #127) and (AnsiCh <> #13) and (AnsiCh <> #10) then
      Result := Result + AnsiCh;
end;
Run Code Online (Sandbox Code Playgroud)

因为UnicodeString你可以做类似的事情.

  • 我不会一遍又一遍地重新分配结果. (6认同)
  • 如果速度成为一个问题,我会解决它. (3认同)
  • @David:哇,你今天对我太严厉了。首先,这是一个代码示例,展示了如何进行正确的比较。优化它会分散人们对这一点的注意力。此外,过早的优化会导致大量的恶意代码。这就是为什么当性能确实是一个问题时我会优化代码。我在代码中添加了一些注释来发出警告,但对我来说,这些警告将与我遇到的大多数证明基本算法的示例代码一起出现。 (2认同)
  • @David:对您来说,这是微不足道的,对我而言,这是微不足道的,但是对于许多SO读者而言,这并非微不足道。这是帕累托原理的经典例子。我教软件开发人员度过了我的一部分,并看到80/20规则是非常固定的。因此,我的样本被很多人理解,需要优化的人会弄清楚自己的意思。我可以理解,您会以不同的方式看到它,但是我认为基于一个代码示例对“草率的程序员”进行注释是很苛刻的方法,尤其是因为它不涉及二次通信。 (2认同)
  • @JeroenWiertPluimers过早的微优化和对语言抽象之下的技术细节的担忧似乎是许多Delphi开发人员的不幸特征(尽管我不知道它在哪里或为什么成为文化的一部分)。因此,我觉得您的有关首先编写干净,清晰的代码,然后仅在必要时进行优化(并且通常在性能分析之后)进行优化的课程比您从字符串中删除字符的说明更为重要! (2认同)

PA.*_*PA. 5

如果您不需要就地执行此操作,但生成该字符串的副本,请尝试此代码

 type CharSet=Set of Char;

 function StripCharsInSet(s:string; c:CharSet):string;
  var i:Integer;
  begin
     result:='';
     for i:=1 to Length(s) do
       if not (s[i] in c) then 
         result:=result+s[i];
  end;  
Run Code Online (Sandbox Code Playgroud)

并像这样使用它

 s := StripCharsInSet(s,[#0..#9,#11,#12,#14..#31,#127]);
Run Code Online (Sandbox Code Playgroud)

编辑:为DEL ctrl char添加了#127.

EDIT2:这是一个更快的版本,感谢ldsandon

 function StripCharsInSet(s:string; c:CharSet):string;
  var i,j:Integer;
  begin
     SetLength(result,Length(s));
     j:=0;
     for i:=1 to Length(s) do
       if not (s[i] in c) then 
        begin
         inc(j);
         result[j]:=s[i];
        end;
     SetLength(result,j);
  end;  
Run Code Online (Sandbox Code Playgroud)

  • 非常慢,它会一遍又一遍地重新分配结果.我将结果设置为与原始字符串相同的长度,而不是在处理完毕后设置实际长度 (3认同)