【问题标题】:How to trim any character (or a substring) from a string?如何从字符串中修剪任何字符(或子字符串)?
【发布时间】:2012-11-21 04:39:10
【问题描述】:

我基本上使用 C#。我可以做到:

string trimmed = str.Trim('\t');

从字符串str 中修剪制表并将结果返回给trimmed

在 delphi7 中,我只找到了Trim,它会修剪空格。

我怎样才能实现相同的功能?

【问题讨论】:

  • 你真的是说你想从一个字符串的末端剪掉一个“子字符串”吗?这不是System.String.Trim 在.Net 中所做的。该函数接受一个 array 字符,然后从当前字符串的任一端修剪所有这些字符。数组中字符的顺序无关紧要。

标签: delphi delphi-7 trim


【解决方案1】:

有字符串助手TStringHelper.Trim 接受 Char 数组作为可选参数。

function Trim(const TrimChars: array of Char): string; overload;

所以,你可以使用

trimmed := str.Trim([#09]);

为你的例子。 #09 这里是 Tab 字符的 ASCII 码。

这个函数至少从 Delphi XE3 开始就存在了。

希望对你有帮助。

【讨论】:

  • 其实是delphi 7问题标签
  • @horgh 哦,对不起。但是问题的作者可能会获取这个函数的来源并为 Delphi 7 重写它。
【解决方案2】:

这是一种有时比找到它所在的位置更容易创建的过程:)

function TrimChar(const Str: string; Ch: Char): string;
var
  S, E: integer;
begin
  S:=1;
  while (S <= Length(Str)) and (Str[S]=Ch) do Inc(S);
  E:=Length(Str);
  while (E >= 1) and (Str[E]=Ch) do Dec(E);
  SetString(Result, PChar(@Str[S]), E - S + 1);
end;

【讨论】:

  • 我试图做类似于你的代码的事情。但你做得更好。
  • 您可以调用 Copy,而不是使用笨拙的 PChar 转换的 SetString。
  • @RobKennedy,同意,Copy 看起来更好,有趣的是在源代码中它们使用不同的装配链,可能以稍微不同的性能结果结束。
【解决方案3】:

在 Delphi 中,Trim 函数不接受参数,但它会修剪其他字符和空格。这是代码(来自 XE2 中的 System.SysUtils,我认为它没有改变):

function Trim(const S: string): string;
var
  I, L: Integer;
begin
  L := Length(S);
  I := 1;
  if (L > 0) and (S[I] > ' ') and (S[L] > ' ') then Exit(S);
  while (I <= L) and (S[I] <= ' ') do Inc(I);
  if I > L then Exit('');
  while S[L] <= ' ' do Dec(L);
  Result := Copy(S, I, L - I + 1);
end;

它正在修剪任何小于 ' ' 的内容,这将消除任何控制字符,如制表符、回车符和换行符。

【讨论】:

【解决方案4】:

Delphi 没有提供满足您需求的功能。内置的Trim 函数始终从输入字符串的两端修剪相同的字符集(空白和控制字符)。这里的几个答案显示了修剪任意字符的基本技术。如您所见,它不必很复杂。这是我的版本:

function Trim(const s: string; c: Char): string;
var
  First, Last: Integer;
begin
  First := 1;
  Last := Length(s);
  while (First <= Last) and (s[First] = c) do
    Inc(First);
  while (First < Last) and (s[Last] = c) do
    Dec(last);
  Result := Copy(s, First, Last - First + 1);
end;

为了适应修剪多个字符,您所要做的就是更改每个循环中的第二个条件项。您将其更改为什么取决于您选择如何表示多个字符。 C# 使用数组。您也可以将所有字符放在一个字符串中,或​​者您可以使用 Delphi 的原生集合类型。

function Trim(const s: string; const c: array of Char): string;
// Replace `s[x] = c` with `CharInArray(s[x], c)`.

function Trim(const s: string; const c: string): string;
// Replace `s[x] = c` with `CharInString(s[x], s)`.

function Trim(const s: string; const c: TSysCharSet): string;
// Replace `s[x] = c` with `s[x] in c`.

CharInArrayCharInString 函数很容易编写:

function CharInArray(c: Char; ar: array of Char): Boolean;
var
  i: Integer;
begin
  Result := True;
  for i := Low(ar) to High(ar) do
    if ar[i] = c then
      exit;
  Result := False;
end;
// CharInString is identical, except for the type of `ar`.

回想一下,在 Delphi 2009 中,CharWideChar 的别名,这意味着它太大而无法放入集合中,因此除非您保证输入会正确,否则您将无法使用集合版本总是适合AnsiChar。此外,s[x] in c 语法会在 WideChar 参数上生成警告,因此您需要改用 CharInSet(s[x], c)。 (与CharInArrayCharInString 不同,RTL 已经为需要它的 Delphi 版本提供了CharInSet。)

【讨论】:

    【解决方案5】:

    你可以使用StringReplace:

    var
      str:String;
    begin
      str:='The_aLiEn'+Chr(VK_TAB)+'Delphi';
    
      ShowMessage(str);
    
      str:=StringReplace(str, chr(VK_Tab), '', [rfReplaceAll]);
    
      ShowMessage(str);
    end;
    

    这会省略给定字符串中的所有制表符。但是你可以改进它,如果你想删除前导和尾随标签,那么你也可以使用 Pos 功能。

    编辑: 对于询问如何使用 Pos 进行操作的评论,这里是:

    var
      str:String;
      s, e: PChar;
    begin
      str:=Chr(VK_TAB)+Chr(VK_TAB)+'The_aLiEn'+Chr(VK_TAB)+'Delphi'+Chr(VK_TAB)+Chr(VK_TAB);
    
      s:=PChar(str);
    
      while Pos(Chr(VK_TAB), s)=1 do inc(s);
      e:=s;
      inc(e, length(s)-1);
      while Pos(Chr(VK_TAB), e)=1 do dec(e);
      str:=Copy(s, 1, length(s)-length(e)+1);
    
      ShowMessage(str);
    end;
    

    当然,这与 Maksee 的相同方法是一样的,而且要做的工作更多。但是,如果没有太多时间来完成这项工作,并且如果 Pos 是您首先想到的,那么可以这样做。你,程序员应该并且必须考虑优化,而不是我。如果我们在谈论优化的约束,稍微调整一下用 char compare 替换 Pos,这将比 Maksee 的代码运行得更快。

    为 Substr 搜索泛化编辑:

    function TrimStr(const Source, SubStr: String): String;
    var
      s, e: PChar;
      l: Integer;
    begin
      s:=PChar(Source);
      l:=Length(SubStr);
    
      while Pos(SubStr, s)=1 do inc(s, l);
      e:=s;
      inc(e, length(s)-l);
      while Pos(SubStr, e)=1 do dec(e, l);
      Result:=Copy(s, 1, length(s)-length(e)+l);
    end;
    

    【讨论】:

    • 您阅读我的问题了吗?我需要修剪字符串,但不要替换其中的所有选项卡
    • 要使这个答案有任何好处,您至少需要演示或描述您认为 Pos 函数如何用于此任务。否则,我觉得你根本没有理解这个问题。
    • @RobKennedy 我添加了一个演示。
    • 为了记录,他也要求 "SubString".. 你如何搜索字符串中的子字符串?
    • 快速说明:VK_xxxvirtual keycodes,不是字符代码。尽管它们可能在值方面匹配并且它们可能永远不会改变,但读者应该意识到像这样的代码是建立在隐含前提上的(这通常是一件坏事)。 #9 将是更惯用的选择,并且仍然提供与编译时翻译相同的性能。
    【解决方案6】:

    JEDI JCL v2.7 为您提供了这些有用的功能:

    function StrTrimCharLeft(const S: string; C: Char): string; function StrTrimCharsLeft(const S: string; const Chars: TCharValidator): string; overload; function StrTrimCharsLeft(const S: string; const Chars: array of Char): string; overload; function StrTrimCharRight(const S: string; C: Char): string; function StrTrimCharsRight(const S: string; const Chars: TCharValidator): string; overload; function StrTrimCharsRight(const S: string; const Chars: array of Char): string; overload; function StrTrimQuotes(const S: string): string;

    【讨论】:

      猜你喜欢
      • 2013-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2017-04-07
      • 2014-03-26
      • 1970-01-01
      相关资源
      最近更新 更多