【发布时间】:2011-05-19 09:01:07
【问题描述】:
在 Delphi XE 下,是否有用于 Copy 的 ANSI 版本? 我经常使用 Copy 来复制 ANSI 字符串。
【问题讨论】:
-
为什么要编辑问题?为什么不接受答案?
-
如果你问我,真正的问题是“为什么 CodeGear 决定首先更改字符串类型?”。谁,在他们正确的头脑中决定破坏几乎所有现有的代码?
在 Delphi XE 下,是否有用于 Copy 的 ANSI 版本? 我经常使用 Copy 来复制 ANSI 字符串。
【问题讨论】:
Altar Delphi 中的Copy 函数是一个内在函数,这意味着它由编译器而不是运行时库处理。根据传递给此函数的参数调用LStrCopy 或UStrCopy 内部函数
检查此示例:
{$APPTYPE CONSOLE}
uses
SysUtils;
Var
s : AnsiString;
u : string;
begin
try
s:='this is a ansi string';
s:= Copy(s,1,5);
Writeln(s);
u:='this is a unicode string';
u:= Copy(u,1,5);
Writeln(u);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Project91.dpr.12: s:='this is a ansi string';
004111DC B8787E4100 mov eax,$00417e78
004111E1 BA04134100 mov edx,$00411304
004111E6 E8314FFFFF call @LStrAsg
Project91.dpr.13: s:= Copy(s,1,5);
004111EB 68787E4100 push $00417e78
004111F0 B905000000 mov ecx,$00000005
004111F5 BA01000000 mov edx,$00000001
004111FA A1787E4100 mov eax,[$00417e78]
004111FF E8A050FFFF call @LStrCopy //call the ansi version of copy
Project91.dpr.14: Writeln(s);
00411204 A1EC2C4100 mov eax,[$00412cec]
00411209 8B15787E4100 mov edx,[$00417e78]
0041120F E84033FFFF call @Write0LString
00411214 E8DF33FFFF call @WriteLn
00411219 E8D22AFFFF call @_IOTest
Project91.dpr.15: u:='this is a unicode string';
0041121E B87C7E4100 mov eax,$00417e7c
00411223 BA28134100 mov edx,$00411328
00411228 E8534EFFFF call @UStrAsg
Project91.dpr.16: u:= Copy(u,1,5);
0041122D 687C7E4100 push $00417e7c
00411232 B905000000 mov ecx,$00000005
00411237 BA01000000 mov edx,$00000001
0041123C A17C7E4100 mov eax,[$00417e7c]
00411241 E8C654FFFF call @UStrCopy //call the unicode version of copy
Project91.dpr.17: Writeln(u);
00411246 A1EC2C4100 mov eax,[$00412cec]
【讨论】:
Copy 是一个“编译器魔术”例程,它由编译器根据您传递的参数(ANSI 字符串、字符串或动态数组)在本质上进行处理。你可以只使用复制;它可以与 ANSI 字符串一起正常工作。
【讨论】:
Copy 的同一调用中不混合使用 unicode 字符串和 ansi 字符串,您将不会收到任何关于编译器的抱怨。
我也有同样的问题,看这段代码:
const
TheStart=13;
TheEnd=69;
type
TMyFileField: Array[TheStart..TheEnd] of Char; // This is a simplification of a field type on a file
procedure WriteWideStringToArrayOfChars(TheLiteral:WideString);
var
MyFileField:TMyFileField; // This is a simplification, it is really a Field inside a File
MyIndex:Integer;
begin
for MyIndex:=1 to Max(Length(TheLiteral),1+TheEnd-TheStart)
do begin // Will copy as many charactes as possible from TheLiteral to MyFileField
MyFileField[MyIndex]:=Copy(TheLiteral,MyIndex,1)[1]; // This gives Copile Error: Incompatible types 'Char' and 'WideChar'
end;
end;
问题是 WideString 必须保存到文件内的 am 数组中。所以必须混合类型......所以,一些松散的Unicode字符会发生,没有办法避免它。
想要的:编译器可以编译它。
解决方案 1:在调用 Copy 之前或在 Copy 内部将 WideString 转换为 String。 解决方案2:在分配之前将 WideChar 转换为 Char。
这里有两种解决方案(记住一些 unicode 字符可能会丢失)...
解决方案1:
MyFileField[MyIndex]:=Copy(UTF8Encode(TheLiteral),MyIndex,1)[1]; // Note: Unicode chars will not get lost, but converted, so beware of accent vocals, etc...
或
MyFileField[MyIndex]:=Copy(String(TheLiteral),MyIndex,1)[1]; // Note: Unicode chars will get lost, they will be converted to '?'
解决方案2:
MyFileField[MyIndex]:=Char(Copy(TheLiteral,MyIndex,1)[1]); // Note: Unicode chars will get lost, they will be converted to '?'
如果有人知道更好的事情,我会很高兴知道。
我个人使用Copy(String(Literal),Start,NumberOfChars),因为正常的重音字母是保守的,更重要的是长度...
示例:长度(字符串('BlaBlaBlá'))-> 9 示例:Length(UTF8Encode('BlaBlaBlá')) -> 大于 9,因为最后一个 'á' 被转换为多个字符等...
希望这可以帮助别人!
【讨论】: