Delphi中arrayofconst应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Delphi中arrayofconst应⽤
Delphi的Format函数⼤家都⽤得很多,第⼆个参数⽤着确实很⽅便。
最近在数据库开发应⽤中需要⾃⼰创建⼀个带array of const参数的函数,对于常⽤的类型String,Integer,Pointer处理都没什么问题,但当⽤到Widestring类型时却出错,摸索了⼀上午,感觉获益良多。
现在将问题、解决问题的思路、分析⽅法等⼀⼀道来,希望对诸君有所启发就达到了我写这篇⽂章的⽬的了!
1. ///环境:Winxp + D7
2. ///进⼊D7,在默认的新建⼯程中增加⼀过程Test(m: Array of const);
3. procedure TForm1.test(m: array of const);
4. var
5. i, zero: Integer;
6. s, t: String;
7. c: Char;
8. const
9. sBoolean: Array [Boolean] of string = ('False', 'True');
10. begin
11. s := '';
12. for i := 0 to High(m) do with m[i] do
13. case VType of //写到这,按住Ctrl点击VType,打开System单元,将VType的枚举值贴到Case语句
14. vtInteger: (VInteger: Integer; VType: Byte);
15. vtBoolean: (VBoolean: Boolean);
16. vtChar: (VChar: Char);
17. vtExtended: (VExtended: PExtended);
18. vtString: (VString: PShortString);
19. vtPointer: (VPointer: Pointer);
20. vtPChar: (VPChar: PChar);
21. vtObject: (VObject: TObject);
22. vtClass: (VClass: TClass);
23. vtWideChar: (VWideChar: WideChar);
24. vtPWideChar: (VPWideChar: PWideChar);
25. vtAnsiString: (VAnsiString: Pointer);
26. vtCurrency: (VCurrency: PCurrency);
27. vtVariant: (VVariant: PVariant);
28. vtInterface: (VInterface: Pointer);
29. vtWideString: (VWideString: Pointer);
30. vtInt64: (VInt64: PInt64);
31. end;
32. Delete(s, 1, 1);
33. Self.Caption := s;
34. end;
35. ///继续写,对各枚举值进⾏处理!这⾥作⼀下解释,Array of const正是由TVarRec类型组成的!
36. ///请看Case of语句中的代码:
37. vtInteger: s := s + ';' + IntToStr(VInteger);
38. vtBoolean: s := s + ';' + sBoolean[VBoolean];
39. vtChar: s := s + ';' + VChar;
40. vtExtended: s := s + ';' + FloatToStr(VExtended^);
41. vtString:
42. if Assigned(VString) then begin
43. t := VString^;
44. s := s + ';' + t;
45. end;
46. vtPointer:
47. if Assigned(VPointer) then
48. s := Format('%S; Pointer: $%X ',[s, Integer(VPointer)]);
49. vtPChar:
50. if Assigned(VPChar) then begin
51. t := VPChar^;
52. s := s + ';' + t;
53. end;
54. vtObject:
55. if Assigned(VObject) then
56. s := Format('%S; $%X ClassName: %S ',[s, Integer(@VObject), VObject.ClassName]);
57. vtClass:
58. if Assigned(VClass) then
59. s := Format('%S; Class Reference $%X - ClassName: %S ',[s, Integer(VClass), VClass.ClassName]);
60. vtWideChar:
61. begin
62. t := VWideChar;
63. s := s + ';' + t;
64. end;
65. vtPWideChar:
66. if Assigned(VPWideChar) then begin
67. t := VPWideChar^;
68. s := s + ';' + t;
69. end;
70. vtAnsiString:
71. if Assigned(VAnsiString) then begin
72. t := PChar(VAnsiString);
73. s := s + ';' + t;
74. end;
75. vtCurrency:
76. if Assigned(VCurrency) then
77. s := s + ';' + FloatToStr(VCurrency^);
78. vtVariant:
79. if Assigned(VVariant) then
80. s := s + '; This is variant ';
81. vtInterface:
82. if Assigned(VInterface) then
83. s := Format('%S; Interface: $%X',[s, Integer(VInterface)]);
84. vtWideString:
85. if Assigned(VWideString) then begin
86. t := PWideString(VWideString)^;
87. s := s + ';' + t;
88. end;
89. vtInt64:
90. if Assigned(VInt64) then
91. s := s + ';' + IntToStr(VInt64^);
92.
加上⼀按钮测试该函数
1. procedure TForm1.Button1Click(Sender: TObject);
2. var
3. ws: WideString;
4. begin
5. ws := 'dda这是⼀个测试dfa';
6. test([self, 'sdf', 2.3324, ws, TForm]);
7. end;
可以看到测试结果,变量ws的值没有显⽰出来,怎么办呢?
我们可以看到WideString类型的值是指针,我们就从这⾥着⼿,在事件中添加⼀句:
Button1.Caption := 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变量都可删除了,代码我就省略了。
Processing math: 100%。