Delphi的Format函数大家都用得很多,第二个参数用着确实很方便。最近在数据库开发应用中需要自己创建一个带array of const参数的函数,对于常用的类型String,Integer,Pointer处理都没什么问题,但当用到Widestring类型时却出错,摸索了一上午,感觉获益良多。现在将问题、解决问题的思路、分析方法等一一道来,希望对诸君有所启发就达到了我写这篇文章的目的了!

///环境:Winxp + D7
///进入D7,在默认的新建工程中增加一过程Test(m: Array of const);
procedure TForm1.test(m: array of const);
var
i, zero: Integer;
s, t: String;
c: Char;
const
sBoolean: Array [Boolean] of string = ('False', 'True');
begin
s := '';
for i := 0 to High(m) do with m[i] do
    case VType of //写到这,按住Ctrl点击VType,打开System单元,将VType的枚举值贴到Case语句
      vtInteger:    (VInteger: Integer; VType: Byte);
      vtBoolean:    (VBoolean: Boolean);
      vtChar:       (VChar: Char);
      vtExtended:   (VExtended: PExtended);
      vtString:     (VString: PShortString);
      vtPointer:    (VPointer: Pointer);
      vtPChar:      (VPChar: PChar);
      vtObject:     (VObject: TObject);
      vtClass:      (VClass: TClass);
      vtWideChar:   (VWideChar: WideChar);
      vtPWideChar: (VPWideChar: PWideChar);
      vtAnsiString: (VAnsiString: Pointer);
      vtCurrency:   (VCurrency: PCurrency);
      vtVariant:    (VVariant: PVariant);
      vtInterface: (VInterface: Pointer);
      vtWideString: (VWideString: Pointer);
      vtInt64:      (VInt64: PInt64);
    end;
Delete(s, 1, 1);
Self.Caption := s;
end;
///继续写,对各枚举值进行处理!这里作一下解释,Array of const正是由TVarRec类型组成的!
///请看Case of语句中的代码:
      vtInteger: s := s + ';' + IntToStr(VInteger);
      vtBoolean: s := s + ';' + sBoolean[VBoolean];
      vtChar: s := s + ';' + VChar;
      vtExtended: s := s + ';' + FloatToStr(VExtended^);
      vtString:
        if Assigned(VString) then begin
          t := VString^;
          s := s + ';' + t;
        end;
      vtPointer:
        if Assigned(VPointer) then
          s := Format('%S; Pointer: $%X ',[s, Integer(VPointer)]);
      vtPChar:
        if Assigned(VPChar) then begin
          t := VPChar^;
          s := s + ';' + t;
        end;
      vtObject:
        if Assigned(VObject) then
          s := Format('%S; $%X ClassName: %S ',[s, Integer(@VObject), VObject.ClassName]);
      vtClass:
        if Assigned(VClass) then
          s := Format('%S; Class Reference $%X - ClassName: %S ',[s, Integer(VClass), VClass.ClassName]);
      vtWideChar:
        begin
          t := VWideChar;
          s := s + ';' + t;
        end;
      vtPWideChar:
        if Assigned(VPWideChar) then begin
          t := VPWideChar^;
          s := s + ';' + t;
        end;
      vtAnsiString:
        if Assigned(VAnsiString) then begin
          t := PChar(VAnsiString);
          s := s + ';' + t;
        end;
      vtCurrency:
        if Assigned(VCurrency) then
          s := s + ';' + FloatToStr(VCurrency^);
      vtVariant:
        if Assigned(VVariant) then
          s := s + '; This is variant ';
      vtInterface:
        if Assigned(VInterface) then
          s := Format('%S; Interface: $%X',[s, Integer(VInterface)]);
      vtWideString:
        if Assigned(VWideString) then begin
          t := PWideString(VWideString)^;
          s := s + ';' + t;
        end;
      vtInt64:
        if Assigned(VInt64) then
          s := s + ';' + IntToStr(VInt64^);

加上一按钮测试该函数

procedure TForm1.Button1Click(Sender: TObject);
var
    ws: WideString;
begin
    ws := 'dda这是一个测试dfa';
    test([self, 'sdf', 2.3324, ws, TForm]);
end;

可以看到测试结果,变量ws的值没有显示出来,怎么办呢?

我们可以看到WideString类型的值是指针,我们就从这里着手,在事件中添加一句:
Button1.Caption := Format('$%X',[Integer(@ws)]);
此句的作用是显示出ws的地址
再在Test函数中也加上类似的语句,并注释掉无用的语句:
//t := PWideString(VWideString)^;
//s := s + ';' + t;
s := s + ';' + Format('$%X',[Integer(VWideString)]);
运行可看到二个地址不一样,说明Delphi对传入的参数数据作了复制
因此将其强制转换成PWidechar应该可以,增加一变量声明
w: WideString;

w := PWideString(VWideString)^;
s := s + ';' + w;
但运行结果却只显示一个字符,别沮丧,已经摸到门道了!

我们知道Format可以处理Widestring类型,这里只得到一个字符,说明字符被截断了。Delphi中的字符串是以#0结束,Widestring以二个#0结束,可以肯定w := PWideString(VWideString)^这句Delphi作转换时肯定将其默认作为AnsiString处理了。分析到这里已经可动手写下去了.....

p: PByte;

if Assigned(VWideString) then begin
          t := '';
          zero := 0;
          p := VWideString;
          repeat
            c := char(p^);
            inc(p);
            if c = #0 then
              inc(zero) else
              begin
                zero := 0;
                t := t + c;
              end;
          until zero = 2;
          s := s + ';' + t;
        end;

但是显示汉字却变成乱码了,而且处理也显得臃肿。到这里我们已经明白了,VWideString所指示的字符串是二字节宽字符串,而且Intel的字节顺序也是低位在前,高位在后。因此可用PWord进行处理!

删除c,zero,w变量,p改成:
p: PWord;

if Assigned(VWideString) then begin
          t := '';
          p := VWideString;
          repeat
            t := t + widechar(p^);
            inc(p);
          until p^ = 0;
          s := s + ';' + t;
        end;
可以看到核心代码已经很精练了,运行已经显示正常,汉字也无乱码了!至此我们似乎是大功告成了,但静下来想想,Delphi支持WideString到String的转换,它也应该有这样的处理代码。
而且在循环中t := t + widechar(p^);语句处下一断点,运行到断点处,再打开CPU窗口,看到看似简洁的代码,单此一句,编译器都要给它加上一大堆处理代码。找到系统的字符串处理函数很有必要,经过在System.pas单元中搜索WideString,找到函数:procedure WideCharToStrVar(Source: PWideChar; var Dest: string);
呵呵,这正是我们要的!!!
现在循环语句及P变量都可删除了,代码我就省略了。

http://www.cnblogs.com/sonicit/archive/2008/03/23/1118524.html

Delphi中array of const应用的更多相关文章

  1. delphi中move函数的正确理解(const和var一样,都是传地址,所以Move是传地址,而恰恰不是传值)太精彩了 good

    我们能看到以下代码var pSource,pDest:PChar;     len: integer;.......................//一些代码Move(pSource,pDest,l ...

  2. Delphi 中 函数参数中的 const 修饰符的本质以及注意事项

    来自:http://blog.csdn.net/farrellcn/article/details/9096787 ------------------------------------------ ...

  3. Delphi中使用比较少的一些语法

    本文是为了加强记忆而写,这里写的大多数内容都是在编程的日常工作中使用频率不高的东西,但是又十分重要. ---Murphy 1,构造和析构函数: a,构造函数: 一般基于TComponent组件的派生类 ...

  4. 谈Delphi中SSL协议的应用(好多相关文章)

    摘要:本文主要介绍如何在Delphi中使用SSL协议.一共分为七个部分:(1)SSL协议是什么?(2)Delphi中如何使用SSL协议?(3)SSL客户端编程实例.(4)SSL服务端编程实例.(5)S ...

  5. 老陈---谈Delphi中SSL协议的应用[转]

    摘要:本文主要介绍如何在Delphi中使用SSL协议.一共分为七个部分:(1)SSL协议是什么?(2)Delphi中如何使用SSL协议?(3)SSL客户端编程实例.(4)SSL服务端编程实例.(5)S ...

  6. [转]Delphi中,让程序只运行一次的方法

    program onlyRunOne; uses Forms,Windows,SysUtils, Dialogs, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} v ...

  7. Delphi中的THashTable

    在Delphi中,Inifiles单元中有一个TStringHash的类,不过它的Value仅支持Integer(其实也不是问题,有其它类型可以将变量变为Pointer),有点不舒服,今天没事做就把它 ...

  8. DELPHI语法基础学习笔记-Windows 句柄、回调函数、函数重载等(Delphi中很少需要直接使用句柄,因为句柄藏在窗体、 位图及其他Delphi 对象的内部)

    函数重载重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同.实际上,编译器是通过检测参数来确定需要调用的例程.下面是从VCL 的数学单元(Math Unit)中摘录的一 ...

  9. 关于Delphi中的字符串的浅析(瓢虫大作,里面有内存错误的举例)

    关于Delphi中的字符串的浅析 只是浅浅的解析下,让大家可以快速的理解字符串. 其中的所有代码均在Delphi7下测试通过. Delphi 4,5,6,7中有字符串类型包括了: 短字符串(Short ...

随机推荐

  1. JAVA SERVLET上传文件的样码

    import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...

  2. android 使用 LocalStorage

    PS:本身是.net 出身 因为项目需要 研究了好几天安卓 这个方法网上也有 自己也写出来 有时间自己看看 和 给还没有解决问题的朋友借鉴下,下面有标个重点 是允许使用localstorage 的关键 ...

  3. 蓝桥杯模拟赛 引爆炸弹-并查集+DFS

    引爆炸弹 在一个 n×m的方格地图上,某些方格上放置着炸弹.手动引爆一个炸弹以后,炸弹会把炸弹所在的行和列上的所有炸弹引爆,被引爆的炸弹又能引爆其他炸弹,这样连锁下去. 现在为了引爆地图上的所有炸弹, ...

  4. (8)C#字符串

    一.字符串 为什么说string是一个不可变的字符序列. string a="me"; a="meeeee"; string b="me" ...

  5. Python的程序结构[5] -> 模块/Module[0] -> 内建模块 builtins

    builtins 内建模块 / builtins Module 在Python的模块中,有一种特殊模块,无需导入便可以使用,其中包含了许多内建函数与类. builtins 模块内容 / builtin ...

  6. TaobaoVM

    作者:Andoter链接:https://www.zhihu.com/question/275665265/answer/416021488来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...

  7. Strobogrammatic Number II -- LeetCode

    A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at upside ...

  8. 【bzoj3261】【最大异或和】可持久化trie树+贪心

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=61705397 Description 给定一个非 ...

  9. 远程访问CENTOS的MYSQL数据库设置

    远程访问CENTOS的MYSQL数据库设置 mysql -u root grant all privileges on *.* to root@'%'identified by 'root'; 后面的 ...

  10. [置顶] kubernetes资源对象--limitranges

    概念 LimitRange(简称limits)基于namespace的资源管理,包括pod和container的最小.最大和default.defaultrequests等. 一旦创建limits,以 ...