Delphi - SysUtils.Trim 不删除最后一个 space(?) 字符

Delphi - SysUtils.Trim not deleting last space(?) char

Delphi里奥。我用 Delphi 构建了一个 Excel 插件(也使用 AddIn Express)。我遍历一列以读取单元格值。读取单元格值后,我执行 TRIM 函数。 TRIM 并没有删除最后一个 space。代码片段...

acctName := Trim(UpperCase(Acctname));

代码前AcctName为'ABC Holdings '。在 TRIM 函数之后是一样的。 Excel 似乎在那里添加了某种类型的其他字符。 (新行??回车return??)摆脱这个的最好方法是什么?有没有办法让调试器显示这个变量的十六进制值。我已经尝试了 INSPECT 和 EVALUATE windows。他们都只显示文字。请注意,我必须小心删除非文本字符,一些公司名称有破折号、逗号、撇号等。

**附加信息 - 根据 Andreas 的建议,我添加了以下内容...

ShowMessage(IntToHex(Ord(Acctname[Acctname.Length])));

返回“00A0”。所以我想我可以做一个简单的 StringReplace...所以我在 Andreas 代码之前添加这个...

 acctName := StringReplace(acctName, #13, '', [rfReplaceAll]);
 acctName := StringReplace(acctName, #10, '', [rfReplaceAll]);

然而,似乎什么都没有改变。 ShowMessage 仍然显示“00A0”作为最后一个字符。为什么 StringReplace 不删除它?

如果您想知道字符串最后一个字符的真实身份,可以显示其 Unicode 代码点:

ShowMessage(IntToHex(Ord(Acctname[Acctname.Length]))). 

或者,您可以使用实用程序调查剪贴板上的 Unicode 字符,例如 my own


是的,有问题的字符是U+00A0: NO-BREAK SPACE

这与通常的 space 类似,但它告诉渲染应用程序不要在此 space 处放置换行符。例如,至少在瑞典语中,您需要 non-breaking spaces in 5 000 kWh.

默认Trim and TStringHelper.Trim不去除这种白色space。 (他们还留下 U+2007: FIGURE SPACE 和其他几种白色 space。)

字符串帮助器方法有一个重载,可让您将字符指定为 trim。您可以使用它来包含 U+00A0:

S.Trim([#, #$A0, #, #$D, #$A]) // space, nbsp, tab, CR, LF
                                    // (many whitespace characters missing!)

但也许更好的解决方案是依靠 Unicode 特性并执行

function RealTrimRight(const S: string): string;
var
  i: Integer;
begin
  i := S.Length;
  while (i > 0) and S[i].IsWhiteSpace do
    Dec(i);
  Result := Copy(S, 1, i);
end;

当然可以实现类似RealTrimLeftRealTrim的功能


当然还有很多方法可以在调试器中查看实际的字符串字节。除了在Evaluate/Modifywindow(Ctrl+F7中写Ord(S[S.Length])之类的东西,我的个人最喜欢的方法是使用Memorywindow(Ctrl+Alt+E)。当它有焦点时,您可以按 Ctrl+G 并键入 S[1] 以查看实际字节数:

在这里您可以看到字符串 test string。由于自 Delphi 2009 年以来字符串是 Unicode (UTF-16),因此每个字符占用两个字节。对于简单的 ASCII 字符,这意味着每隔一个字节为空。我们字符串的 ASCII 值是 74 65 73 74 20 73 74 72 69 6E 67。您还可以看到,在上面的行 (02A0855C) 中,我们的字符串对象具有引用计数 1 和长度 B (=11).

作为演示,显示 unicode 字符串:

program q63847533;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;
type
  array100              = array[0..99] of Byte;
  parray100             = ^array100;
var
  searchResult          : TSearchRec;
  Name                  : string;
  display               : parray100 absolute Name;
  dummy                 : string;

begin
  if findfirst('z*.mp3', faAnyFile, searchResult) = 0 then
  begin
    repeat
      writeln('File name = '+searchResult.Name);
      name := searchResult.Name;
      writeln('File size = '+IntToStr(searchResult.Size));
    until FindNext(searchResult) <> 0;

    // Must free up resources used by these successful finds
    FindClose(searchResult);
  end;
  readln(dummy);
end.

我的目录包含两个 z*.mp3 文件,一个具有 ANSI 名称,另一个具有 Unicode 名称。

WATCHing display^ as Hex 或 Memorydump 将显示您似乎需要的内容(您问题的 Is there a way I can ask the debugger to show me the HEX value for this variable.