1

我正在慢慢地将现有代码转换为 Delphi 2010,并阅读了 Embarcaedro 网站上的几篇文章以及 Marco Cantú 白皮书。

还有一些我没有理解的东西,所以这里有两个函数来举例说明我的问题:

function RemoveSpace(InStr: string): string;
var
  Ans     : string;
  I       : Word;
  L       : Word;
  TestChar: string[1];
begin
  Ans := '';
  L := Length(InStr);
  if L > 0 then
  begin
    for I := 1 to L do
    begin
      TestChar := Copy(InStr, I, 1);
      if TestChar <> ' ' then Ans := Ans + TestChar;
    end;
  end;
  RemoveSpace := Ans;
end;

function ReplaceStr(const S, Srch, Replace: string): string;
var
  I: Integer;
  Source: string;
begin
  Source := S;
  Result := '';
  repeat
    I := Pos(Srch, Source);
    if I > 0 then begin
      Result := Result + Copy(Source, 1, I - 1) + Replace;
      Source := Copy(Source, I + Length(Srch), MaxInt);
    end
    else Result := Result + Source;
  until I <= 0;
end;

对于 RemoveSpace 函数,如果没有传递 unicode 字符(例如“aa bb”),则一切正常。现在,如果我传递文本“ab cd”,则该函数无法按预期工作(我得到 ab??cd 作为输出)。

如何解释字符串上可能的 unicode 字符?使用 Length(InStr) 和 Copy(InStr, I, 1) 显然是不正确的。

转换此代码以使其包含 unicode 字符的最佳方法是什么?

谢谢!

4

5 回答 5

14

如果这些是您的真实功能并且您只是想让它们工作,那么:

function RemoveSpace(const InStr: string): string;
begin
  Result := StringReplace(InStr, ' ', '', [rfReplaceAll]); 
end;

function ReplaceStr(const S, Srch, Replace: string): string;
begin
  Result := StringReplace(S, Srch, Replace, [rfReplaceAll, rfIgnoreCase]); 
end;
于 2009-10-07T12:46:24.457 回答
1

虽然string现在是 Unicode 类型,但是当你指定一个长度时,你仍然会得到非 UnicodeShortString类型。函数中的TestChar变量RemoveSpace是非 Unicode 单字符字符串。你应该一直使用的是一个真正的Char变量。我希望您来自 VB 世界,其中一个字符的字符串与单个字符相同。在 Delphi 中,字符串与字符不同,因此当您调用 时Copy,您会得到一个字符串。

在 Unicode Delphi 中,该单字符字符串被简化为非 Unicode 字符串,如果当前代码页中没有该字符的表示形式,则您会得到一个问号。像这样修复它:

function RemoveSpace(const InStr: string): string;
var
  I: Integer;
  TestChar: Char;
begin
  Result := '';
  for I := 1 to Length(InStr) do
  begin
    TestChar := InStr[I];
    if TestChar <> ' ' then
      Result := Result + TestChar;
  end;
end;

我摆脱了Ans。从 Turbo Pascal 7 开始,您可以使用隐式声明的Result变量,而不是声明自己的变量,然后将其分配给函数名。Result是可读可写的。此外,您无需担心零长度输入。当“for-to”循环的上限小于下限时,循环根本不会运行,因此您无需事先检查。最后,我使用括号运算符InStr来提取给定索引处的字符,而不是获取一个字符长的字符串。

你说你对LengthandCopy的使用显然是不正确的,但你错了。这些函数在 Unicode 中继续正常工作。他们知道现在Char是两个字节宽,所以如果你在UnicodeString变量上调用它们,你会得到正确的字符。他们还继续研究AnsiString变量。事实上,它们也适用于WideString变量查找,即使在较旧的 Delphi 版本中也是如此。

代码中的主要问题是将 Unicode 字符存储到非 Unicode 字符串类型中。

于 2009-10-07T15:09:17.340 回答
1

(我们目前不使用 D10,所以要小心!)

Delphi 中的问题在于包含基本 ascii 范围之外的字符的字符串文字。当它们传递给字符串例程时,非 ascii 字符将替换为问号。

为避免这种情况,请将文本文字转换为 WideStrings,然后再将它们作为参数传递给函数。

我不知道它是否适用于 StringReplace 例程,但 Delphi 的搜索例程 Pos/Posex 不能正确处理 Unicode。我们必须用我们自己的变体替换这些例程。对于这个改进的例程,重要的是要确保参数是 WideString 类型,而不是普通的字符串类型。

在处理 Unicode 时,我们在 D7 中这样做了,并且一切正常。

于 2009-10-07T14:59:16.080 回答
0

String[1] 没有 unicode 版本

试试 Char。

于 2010-02-03T06:58:25.277 回答
0

根据您的问题描述猜测,您似乎在处理 UTF8 编码的字符串。这几乎总是一个坏主意。首先将它们解码为更合理的表示,然后对它们进行操作。完成后,您可以再次将所有内容编码为 UTF-8。

我认为宽字符串的数据类型是 Delphi 中的“WString”;现在查不出来。

于 2009-10-07T12:27:36.027 回答