2009-10-07 85 views
1

我正在慢慢地将现有代码转换为Delphi 2010,并阅读Embarcaedro网站以及MarcoCantú白皮书中的几篇文章。将函数转换为delphi 2009/2010(unicode)

仍然有一些事情我没有理解,所以这里有两个函数来举例说明我的问题:

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字符?

谢谢!

+0

咦?字作为字符串的长度和索引的类型?从Delphi 3开始生产代码?除了Aldo的解决方案,我建议你确保你的代码编译时没有警告(甚至更好:没有提示)。 – 2009-10-08 09:18:02

+0

Jeroen,我在这段代码中看不到会产生警告或提示。为Word分配一个整数不会生成一条消息;不过,它可能会导致长度超过65535个字符的范围检查错误。对于永远不能为负数的变量(如字符串长度和索引),使用无符号类型是很常见的,而在Delphi 3中,Word是可用的最大无符号类型。 (真正的无符号红衣主教只能排在德尔福4,引进的Int64的。) – 2009-10-08 16:10:41

回答

14

如果这些是你的真实功能,你只是试图让那么EM工作:

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; 
+0

谢谢,这些的确是约会从D3或D4,我从来没有抽时间去升级他们回到真正的功能。 – smartins 2009-10-07 14:49:35

0

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

我认为宽字符字符串的数据类型是Delphi中的“WString”现在无法查看它。

1

(我们不使用D10,此刻,所以要小心!)

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

为避免出现这种情况,请在将文本文字作为参数传递给函数之前,将文本文字转换为WideStrings。

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

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

+1

我不会去想这WideStrings建议是正确的(至少,不为D2010)。一个WideString的是一个非引用计数宽(Unicode的)串,主要用于COM我想。在2009年之前,它是唯一可以使用的支持Unicode的字符串,而不再是这种情况。此外,没有任何关于将(Unicode)字符串传递给字符串函数,使“非ASCII字符被替换为问号”(转换为ANSI),除非您向下转换为AnsiString。最简单的解决方案就是不要这么做 - 在整个应用程序中使用“string”作为字符串类型。 – 2009-10-07 22:52:05

+0

我明确提到我们在D7中观察到了这种行为! 的问题表现在非ASCII文字与“+”连接在一起 - 运营商。然后它们被隐式转换为Ansi,非asii字符被替换为问号。这种行为并非由我们明确投射给Ansi引起的!解决方案很简单:在连接之前显式转换为WideString。 显示这个问题的单元测试正好在我面前,所以我没有做到这一点。我们在我们的代码库中使用String作为onlstring类型。 – user93066 2009-10-08 09:10:39

1

虽然string现在是Unicode类型,但在指定长度时,仍然会得到非Unicode ShortString类型。 RemoveSpace函数中的TestChar变量是一个非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支架运营商给定的索引而不是得到一个字符的长串,对提取字符

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

在你的代码的主要问题是您存储Unicode字符到非Unicode字符串类型。

+0

我很想为我的回答和问题解释一下downvotes。 – 2009-10-08 03:19:29

+0

+1为解释为什么字符串[1]是问题。 “教一个人钓鱼”等等。 – 2009-10-13 01:53:40

0

字符串[1]没有unicode版本

请尝试改为Char。