【问题标题】:Is there an ANSI version for Copy?Copy 有 ANSI 版本吗?
【发布时间】:2011-05-19 09:01:07
【问题描述】:

在 Delphi XE 下,是否有用于 Copy 的 ANSI 版本? 我经常使用 Copy 来复制 ANSI 字符串。

【问题讨论】:

  • 为什么要编辑问题?为什么不接受答案?
  • 如果你问我,真正的问题是“为什么 CodeGear 决定首先更改字符串类型?”。谁,在他们正确的头脑中决定破坏几乎所有现有的代码?

标签: delphi unicode


【解决方案1】:

Altar Delphi 中的Copy 函数是一个内在函数,这意味着它由编译器而不是运行时库处理。根据传递给此函数的参数调用LStrCopyUStrCopy 内部函数

检查此示例:

{$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,或者我只是在 Copy 周围放置一个 $Warnings?
  • 混音是一场性能噩梦。你为什么不尽可能地转换,一种方式(显式 AnsiString)或所有其他方式(显式转到 String aka UnicodeString)。
  • +1 for Warren:为了混合字符串并保持性能,请确保在调用某些高级函数(如 IntToStr 等)时,您调用的是 Ansi 或 Unicode 版本...没那么容易...我必须在 Unicode 版本的 Delphi 下创建具有最佳性能的my own set of dedicated functions to handle UTF-8 strings。函数重载可能难以跟踪。
【解决方案2】:

Copy 是一个“编译器魔术”例程,它由编译器根据您传递的参数(ANSI 字符串、字符串或动态数组)在本质上进行处理。你可以只使用复制;它可以与 ANSI 字符串一起正常工作。

【讨论】:

  • 我希望有一个 ANSI 版本在我将 ANSI 字符串传递给它时不会报错。所以我不必在我的代码中将 UNICODE 类型转换为 ANSI。
  • 正如我所说,Copy 已经是 ANSI。您不必进行类型转换,编译器也不会抱怨。将其视为一个重载过程,其中一个重载版本接受 ANSI 字符串参数。
  • Altar 如果您在对Copy 的同一调用中不混合使用 unicode 字符串和 ansi 字符串,您将不会收到任何关于编译器的抱怨。
  • 好吧,这就是编译器抱怨的原因。我使用混合类型。
【解决方案3】:

我也有同样的问题,看这段代码:

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,因为最后一个 'á' 被转换为多个字符等...

希望这可以帮助别人!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-24
    • 2017-04-11
    • 2012-12-17
    • 2012-12-07
    • 2011-06-16
    • 2010-11-28
    • 1970-01-01
    相关资源
    最近更新 更多