我正在慢慢将现有代码转换为Delphi 2010并阅读Embarcaedro网站上的几篇文章以及MarcoCantú白皮书。
还有一些我还没有理解的东西,所以这里有两个函数来举例说明我的问题:
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字符?使用长度(InStr)显然不正确以及复制(InStr,I,1)。
转换此代码以解决unicode字符的最佳方法是什么?
谢谢!
答案 0 :(得分: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;
答案 1 :(得分:1)
(我们现在不使用D10,所以要小心!)
Delphi中的问题是字符串文字包含基本ascii-range之外的字符。当它们传递给字符串例程时,非ascii字符将替换为问号。
要避免这种情况,请将文本文字转换为WideStrings,然后再将它们作为参数传递给函数。
我不知道它是否适用于StringReplace例程,但Delphi的搜索例程Pos / Posex无法正确处理Unicode。我们不得不用我们自己的变体替换这些例程。对于这个改进的例程,重要的是确保参数是WideString类型,而不是普通的字符串类型。
我们在处理Unicode时在D7中做到了这一点,并且一切正常。
答案 2 :(得分:1)
虽然string
现在是Unicode类型,但是当您指定长度时,仍然会获得非Unicode ShortString
类型。 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
上的括号运算符来提取给定索引处的字符,而不是获取一个字符长的字符串。
您说Length
和Copy
的使用显然不正确,但您错了。这些函数在Unicode中继续正常工作。他们知道Char
现在是两个字节宽,所以如果你在UnicodeString
个变量上调用它们,你就会获得正确的字符。他们还继续研究AnsiString
变量。事实上,他们也可以找到WideString
变量,即使在较旧的Delphi版本中也是如此。
代码中的主要问题是将Unicode字符存储到非Unicode字符串类型中。
答案 3 :(得分:0)
从您的问题描述中猜测,您似乎处理UTF8编码的字符串。这几乎总是一个坏主意。首先将它们解码为更健全的表示,然后对它们进行操作。完成后,您可以再次将所有内容编码为UTF-8。
我认为宽字符串的数据类型是Delphi中的“WString”;现在看不起来。
答案 4 :(得分:0)
String [1]没有unicode版本
尝试使用Char。