静态数组的定义方法
//1. 标准方法:
var
MyArr:
array[
0..10]
of Integer;
//定义静态数组
//2. 可以使用非0下标:
var
MyArr:
array[
9..10]
of Integer;
//不能提倡,这样不容易与系统函数沟通
//3. 根据预定义类型来声明数组:
type
TMyArr =
array[
0..10]
of Integer;
//先定义一个数组类型
var
MyArr: TMyArr;
//再定义静态数组
//4. 在非过程区可以直接赋值:
var
MyArr:
array[
0..2]
of Integer = (
11,
22,
33);
//5. 多维数组:
var
MyArr:
array[
0..2,
0..2]
of Integer;
begin
//使用
MyArr[
1,
2] :=
100;
end;
//6. 根据子界定义数组:
type
TRange =
0..10;
var
MyArr:
array[TRange]
of Integer;
//7. 根据枚举定义数组:
type
TEnums = (Enum1,Enum2,Enum3);
var
MyArr:
array[TEnums]
of string;
begin
MyArr[Enum1] :=
'万一';
ShowMessage(MyArr[Enum1]);
//万一
end;
//8. 根据其他类型定义数组:
var
MyArr:
array[Byte]
of Char;
begin
MyArr[
255] :=
#65;
ShowMessage(MyArr[
255]);
//A
end;
//应尽量不使用内建类型,可以新建类型:
type
TNewByte = Byte;
var
MyArr:
array[TNewByte]
of Char;
begin
MyArr[
255] :=
#65;
ShowMessage(MyArr[
255]);
//A
end;
//也可以使用类型别名:
type
TChar =
type Char;
var
MyArr:
array[TChar]
of Byte;
begin
MyArr[
'C'] :=
255;
ShowMessage(IntToStr(MyArr[
'C']));
//255
end;
//同时定义类型:
type
MyRec =
record
s:
string;
r: Real;
b: Byte;
end;
var
Arr1:
array[
0..100]
of MyRec;
Arr2:
array[
0..100]
of record s:
string; r: Real; b: Byte;
end;
//可以直接这样定义
Arr3:
packed array[
0..100]
of MyRec;
//压缩数组定义, 好像没有区别?
动态数组的使用
//例1:
var
StrArr:
array of String;
//动态数组定义时不与维数
begin
SetLength(StrArr,
6);
//分配6个元素位置: 0-5
StrArr[
0] :=
'万一';
//动态数组的下界是 0
ShowMessage(StrArr[
0]);
//分配空间后和静态数组一样使用
StrArr :=
nil;
//一般没必要手动释放, 动态数组离开作用域会自释放
end;
//例2. 动态数组的引用:
var
Arr1,Arr2:
array of Integer;
a:
array[
0..1]
of Integer;
begin
SetLength(Arr1,
6);
Arr1[
5] :=
100;
Arr2 := Arr1;
//Arr2 引用了 Arr1
ShowMessage(IntToStr(Arr2[
5]));
//100
ShowMessage(IntToStr(Length(Arr2)));
//当然 Arr2 维数也会是 6
ShowMessage(IntToStr(SizeOf(Arr1)));
//4, 其实动态数组是个指针
ShowMessage(IntToStr(SizeOf(Arr2)));
//4
Arr2[
5] :=
99;
//现在它们指向同一个数组, 改变这个就是改变那个
ShowMessage(IntToStr(Arr1[
5]));
//99
Arr1 :=
nil;
//释放其中一个指针, 数组继续存在
ShowMessage(IntToStr(Arr2[
5]));
//99
end;
//例3. 数组 Copy <1>:
var
Arr1,Arr2:
array of Integer;
begin
SetLength(Arr1,
6);
Arr1[
5] :=
100;
Arr2 := Copy(Arr1);
//数组 Copy
Arr2[
5] :=
99;
//改变 Arr2 不再影响 Arr1
ShowMessage(IntToStr(Arr1[
5]-Arr2[
5]));
//1
SetLength(Arr1,
7);
ShowMessage(IntToStr(Length(Arr1)));
//7
ShowMessage(IntToStr(Length(Arr2)));
//6, 没有一点牵扯了
end;
//例4. 数组 Copy <2>:
var
Arr1,Arr2:
array of Integer;
i: Integer;
begin
SetLength(Arr1,
6);
for i := Low(Arr1)
to High(Arr1)
do //给每个元素赋值
Arr1[i] := i+
1;
Arr2 := Copy(Arr1,
1,
3);
//只 Copy 第2..4个元素
ShowMessage(IntToStr(Arr1[
1]));
//2, 现在 Arr2[0] 和 Arr1[1] 的值是一样的
ShowMessage(IntToStr(Arr2[
0]));
//2
ShowMessage(IntToStr(Length(Arr1)));
//6, 维数肯定不一样了
ShowMessage(IntToStr(Length(Arr2)));
//3
end;
//例5. 动态多维数组:
var
Arr:
array of array of Integer;
//定义多维数组
begin
SetLength(Arr,
5,
5);
//分配空间
Arr[
0,
3] :=
100;
//赋值
ShowMessage(IntToStr(Arr[
0,
3]));
//取值
end;
//例6. 另类建立:
var
Arr:
array of Integer;
begin
Arr := varArrayCreate([
0,
3],varInteger);
ShowMessage(IntToStr(Length(Arr)));
//4
Arr := VarArrayOf([
1,
2,
3,
4]);
ShowMessage(IntToStr(Arr[
0]));
//1
{这是给变体数组使用的,可能会有效率问题}
end;
变体数组
var
Arr:
array[
0..3]
of Variant;
begin
Arr[
0] :=
123;
Arr[
1] :=
'wy';
Arr[
2] := True;
Arr[
3] := VarArrayOf([
1,
'wanyi',
1.5]);
//变体数组的元素也可以是变体数组
ShowMessage(Arr[
0]);
//123, 不需要转换
ShowMessage(Arr[
1]);
//wy
ShowMessage(Arr[
2]);
//True
ShowMessage(Arr[
3][
1]);
//wanyi
end;
数组与枚举
type
TMyEnum = (Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday);
{定义枚举}
var
weekArr:
array[TMyEnum]
of string;
{定义数组}
myEnum: TMyEnum;
{定义枚举变量}
begin
{数组赋值}
weekArr[Monday] :=
'星期一';
weekArr[Tuesday] :=
'星期二';
weekArr[Wednesday] :=
'星期三';
weekArr[Thursday] :=
'星期四';
weekArr[Friday] :=
'星期五';
weekArr[Saturday] :=
'星期六';
weekArr[Sunday] :=
'星期天';
{调用数组}
ShowMessage(weekArr[Sunday]);
{星期天}
{遍历数组}
for myEnum := Low(weekArr)
to High(weekArr)
do
begin
ShowMessage(weekArr[myEnum]);
{将分别显示: 星期一 ... 星期天}
end;
end;
数组与子界
type
TABC =
'A'..'G';
{定义子界}
var
abcArr:
array[TABC]
of Integer;
{定义数组}
abc: TABC;
{定义子界变量}
begin
{数组赋值}
abcArr[
'A'] :=
11;
abcArr[
'B'] :=
22;
abcArr[
'C'] :=
33;
abcArr[
'D'] :=
44;
abcArr[
'E'] :=
55;
abcArr[
'F'] :=
66;
abcArr[
'G'] :=
77;
{调用数组}
ShowMessage(IntToStr(abcArr[
'G']));
{77}
{遍历数组}
for abc := Low(abcArr)
to High(abcArr)
do
begin
ShowMessage(IntToStr(abcArr[abc]));
{11 22 33 44 55 66 77}
end;
end;
动态数组的释放
//动态数组一般是不需要手动释放的, 如果需要...
var
arr:
array of Integer;
begin
{设置动态数组维数}
SetLength(arr,
10);
{释放方法一}
arr :=
nil;
{释放方法二}
SetLength(arr,
0);
{释放方法三}
Finalize(arr);
end;
数组竟然可以这样定义
//这是常规思路:
const
arr:
array[
0..1]
of Char = (
'A',
'B');
begin
ShowMessage(arr);
{AB}
ShowMessage(IntToStr(Length(arr)));
{2}
end;
//没想到可以这样:
const
arr:
array[Boolean]
of Char = (
'A',
'B');
begin
ShowMessage(arr);
{AB}
ShowMessage(IntToStr(Length(arr)));
{2}
{访问元素}
ShowMessage(arr[False]);
{A}
ShowMessage(arr[True]);
{B}
{也可以这样访问}
ShowMessage(arr[Low(arr)]);
{A}
ShowMessage(arr[High(arr)]);
{B}
{但不能这样访问}
// ShowMessage(arr[0]);
// ShowMessage(arr[1]);
{但可以变通一下}
ShowMessage(arr[Boolean(
0)]);
{A}
ShowMessage(arr[Boolean(
1)]);
{B}
end;
//同理, 这样也可以:
const
arr:
array[Byte]
of Integer = (
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126,
127,
128,
129,
130,
131,
132,
133,
134,
135,
136,
137,
138,
139,
140,
141,
142,
143,
144,
145,
146,
147,
148,
149,
150,
151,
152,
153,
154,
155,
156,
157,
158,
159,
160,
161,
162,
163,
164,
165,
166,
167,
168,
169,
170,
171,
172,
173,
174,
175,
176,
177,
178,
179,
180,
181,
182,
183,
184,
185,
186,
187,
188,
189,
190,
191,
192,
193,
194,
195,
196,
197,
198,
199,
200,
201,
202,
203,
204,
205,
206,
207,
208,
209,
210,
211,
212,
213,
214,
215,
216,
217,
218,
219,
220,
221,
222,
223,
224,
225,
226,
227,
228,
229,
230,
231,
232,
233,
234,
235,
236,
237,
238,
239,
240,
241,
242,
243,
244,
245,
246,
247,
248,
249,
250,
251,
252,
253,
254,
255,
256);
begin
ShowMessage(IntToStr(arr[Low(arr)]));
{1}
ShowMessage(IntToStr(arr[High(arr)]));
{256}
ShowMessage(IntToStr(Length(arr)));
{256}
end;
//给这种用法来一个必要性的实例:
const
BoolStr:
array[Boolean]
of string = (
'False',
'True');
var
b: Boolean;
begin
b := True;
ShowMessage(BoolStr[b]);
{True}
b :=
not b;
ShowMessage(BoolStr[b]);
{False}
end;
#4楼
2008-09-10 18:43
蓝色光芒 [未注册用户]
我来提醒大家
数组定义时,如果唯数是以枚举开始的话,编译指令是从Low()..High()
所以带有负数值的枚举用来定义数组常量会出错.
如:
Type
TErrorCode = (ecNOERROR = 0,
ecDisConnect = -1,
ecOtherError = -2);
Const
ErrorLabels : array [TErrorCode] of String =(
'无错误' , '断开连接' , '其他错误');
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption := ErrorLabels[ecOtherError];
end;
Caption得到的是:无错误,那是因为Low(TErrorCode)=ecOtherError
High(TErrorCode)就是ecNOERROR
开放数组参数
//给一个整型开放数组求和的函数
function MyFun(
const arr:
array of Integer): Integer;
var
i: Integer;
begin
Result :=
0;
for i
in arr
do Result := Result + i;
end;
{测试1:}
procedure TForm1
.Button1Click(Sender: TObject);
var
num: Integer;
begin
num := MyFun([
1,
2,
3]);
ShowMessage(IntToStr(num));
{6}
end;
{测试2:}
procedure TForm1
.Button2Click(Sender: TObject);
var
iArr:
array of Integer;
i,x: Integer;
begin
SetLength(iArr,
10);
for i := Low(iArr)
to High(iArr)
do
begin
iArr[i] := i +
1;
end;
x := MyFun(iArr);
ShowMessage(IntToStr(x));
{55}
end;
关于 array of const
之前应该参考一下: 关于开放数组参数
//这是在 System 单元定义的一组标识数据类型的常量:
vtInteger =
0;
vtBoolean =
1;
vtChar =
2;
vtExtended =
3;
vtString =
4;
vtPointer =
5;
vtPChar =
6;
vtObject =
7;
vtClass =
8;
vtWideChar =
9;
vtPWideChar =
10;
vtAnsiString =
11;
vtCurrency =
12;
vtVariant =
13;
vtInterface =
14;
vtWideString =
15;
vtInt64 =
16;
//这是定义在 System 单元关于数据类型的一个结构:
TVarRec =
record
case Byte
of
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;
作为参数的开放数组, 有时数组的成员类型是不确定的, 此时应该使用 array of const 定义; 详细举例:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{把不同数据类型返回字符串的函数}
function Fun1(arr:
array of const):
string;
var
i: Integer;
begin
Result :=
'';
for i := Low(arr)
to High(arr)
do
begin
case arr[i].VType
of
vtInteger : Result := Result + IntToStr(arr[i].VInteger) +
' ';
vtBoolean : Result := Result + BoolToStr(arr[i].VBoolean, True) +
' ';
vtChar : Result := Result + arr[i].VChar +
' ';
vtExtended : Result := Result + FloatToStr(arr[i].VExtended^) +
' ';
vtString : Result := Result + PShortString(arr[i].VString)^ +
' ';
vtPointer : Result := Result + IntToStr(Integer(arr[i].VPointer)) +
' ';
vtPChar : Result := Result + arr[i].VPChar +
' ';
vtObject : Result := Result + arr[i].VObject
.ClassName +
' ';
vtClass : Result := Result + arr[i].VClass
.ClassName +
' ';
vtWideChar : Result := Result + arr[i].VWideChar +
' ';
vtPWideChar : Result := Result + arr[i].VPWideChar +
' ';
vtAnsiString: Result := Result + PAnsiChar(arr[i].VAnsiString)^ +
' ';
vtCurrency : Result := Result + CurrToStr(arr[i].VCurrency^) +
' ';
vtVariant : Result := Result +
string(arr[i].VVariant^) +
' ';
vtInterface : Result := Result + IntToStr(Integer(arr[i].VInterface)) +
' ';
vtWideString: Result := Result + PWideChar(arr[i].VWideString) +
' ';
vtInt64 : Result := Result + IntToStr(arr[i].VInt64^) +
' ';
end;
end;
end;
{简化上一个函数}
function Fun2(
const arr:
array of const):
string;
var
i: Integer;
const
n =
#32;
begin
Result :=
'';
for i := Low(arr)
to High(arr)
do with arr[i]
do
begin
case VType
of
0 : Result := Result + IntToStr(VInteger) + n;
1 : Result := Result + BoolToStr(VBoolean, True) + n;
2 : Result := Result + VChar + n;
3 : Result := Result + FloatToStr(VExtended^) + n;
4 : Result := Result + PShortString(VString)^ + n;
5 : Result := Result + IntToStr(Integer(VPointer)) + n;
6 : Result := Result + VPChar + n;
7 : Result := Result + VObject
.ClassName + n;
8 : Result := Result + VClass
.ClassName + n;
9 : Result := Result + VWideChar + n;
10: Result := Result + VPWideChar + n;
11: Result := Result + PAnsiChar(VAnsiString)^ + n;
12: Result := Result + CurrToStr(VCurrency^) + n;
13: Result := Result +
string(VVariant^) + n;
14: Result := Result + IntToStr(Integer(VInterface)) + n;
15: Result := Result + PWideChar(VWideString) + n;
16: Result := Result + IntToStr(VInt64^) + n;
end;
end;
end;
{获取类型名的函数}
function Fun3(
const arr:
array of const):
string;
var
i: Integer;
const
n = sLineBreak;
begin
Result :=
'';
for i := Low(arr)
to High(arr)
do with arr[i]
do
begin
case VType
of
0 : Result := Result +
'Integer' + n;
1 : Result := Result +
'Boolean' + n;
2 : Result := Result +
'Char' + n;
3 : Result := Result +
'Extended' + n;
4 : Result := Result +
'String' + n;
5 : Result := Result +
'Pointer' + n;
6 : Result := Result +
'PChar' + n;
7 : Result := Result +
'Object' + n;
8 : Result := Result +
'Class' + n;
9 : Result := Result +
'WideChar' + n;
10: Result := Result +
'PWideChar' + n;
11: Result := Result +
'AnsiString'+ n;
12: Result := Result +
'Currency' + n;
13: Result := Result +
'Variant' + n;
14: Result := Result +
'Interface' + n;
15: Result := Result +
'WideString'+ n;
16: Result := Result +
'Int64' + n;
end;
end;
end;
{测试}
procedure TForm1
.Button1Click(Sender: TObject);
var
a: Integer;
b: Boolean;
c: Char;
d: Extended;
e: ShortString;
f: Pointer;
g: PChar;
h: TButton;
i: TClass;
j: WideChar;
k: PWideChar;
l: AnsiString;
m: Currency;
n: Variant;
o: IInterface;
p: WideString;
q: Int64;
begin
a :=
1;
b := True;
c :=
'a';
d :=
2;
e :=
'S';
f := Pointer(
3);
g :=
'P';
h := TButton(Sender);
i := TForm;
j :=
#19975;
k :=
'一';
l :=
'A';
m :=
4;
n :=
5;
//o;
p :=
'万一';
q :=
7;
ShowMessage(Fun1([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q]));
ShowMessage(Fun2([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q]));
{结果如下:}
{1 True a 2 S 3 P TButton TForm 万 一 A 4 5 0 万一 7 }
ShowMessage(Fun3([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q]));
{结果如下:
Integer
Boolean
Char
Extended
String
Pointer
PChar
Object
Class
WideChar
PWideChar
AnsiString
Currency
Variant
Interface
WideString
Int64
}
end;
{我试试没有在 TVarRec 中的类型是怎么归类的}
procedure TForm1
.Button2Click(Sender: TObject);
var
a: Byte;
b: Word;
c: Cardinal;
d: Double;
e: Real;
f: TStrings;
begin
ShowMessage(Fun3([a,b,c,d,e,f]));
{结果如下:
Integer
Integer
Integer
Extended
Extended
Object
}
end;
end.
从这个例子中还能得到的启示是(根据网友的提示, 下面可能理解错了!):
//不超过 4 字节的简单类型, 在内存中只有一个存放处.
Integer;
Boolean;
Char;
WideChar;
//超过 4 字节的类型(包括字符串), 在内存中有两个存放处: 一个是指针位置; 一个是数据位置.
Int64;
//俺在D7中内存就一个数据位置
Extended;
Currency;
Variant;
ShortString;
AnsiString;
WideString;
//指针: 只有 4 字节大小.
Pointer;
PChar(PAnsiChar);
PWideChar;
//对象: 复杂了...
Object
Class;
IInterface;
判断一个数组的长度用 Length 还是 SizeOf ?
最近发现一些代码, 甚至有一些专家代码, 在遍历数组时所用的数组长度竟然是 SizeOf(arr); 这不合适!如果是一维数组、且元素大小是一个字节, 这样用看不出错误, 譬如:
var
arr1:
array[
0..9]
of Char;
arr2:
array[
0..9]
of Byte;
begin
ShowMessageFmt(
'%d,%d,%d,%d',[Length(arr1), SizeOf(arr1),
Length(arr2), SizeOf(arr2)]);
{显示结果: 10,10,10,10}
end;
但如果数组元素多于一个字节、或是多维数组的情况下, 就不行了, 举例:
const
arr1:
array[
0..9]
of Integer = (
1,
2,
3,
4,
5,
6,
7,
8,
9,
10);
arr2:
array[
0..1,
0..3]
of Integer = ((
1,
2,
3,
4), (
5,
6,
7,
8));
var
arr3:
array[Boolean]
of Integer;
arr4:
array[Byte]
of Integer;
begin
ShowMessage(IntToStr(Length(arr1)));
{10}
ShowMessage(IntToStr(SizeOf(arr1)));
{40}
ShowMessage(IntToStr(Length(arr2)));
{2}
ShowMessage(IntToStr(Length(arr2[
0])));
{4}
ShowMessage(IntToStr(Length(arr2[
1])));
{4}
ShowMessage(IntToStr(SizeOf(arr2)));
{32}
ShowMessage(IntToStr(Length(arr3)));
{2}
ShowMessage(IntToStr(SizeOf(arr3)));
{8}
ShowMessage(IntToStr(Length(arr4)));
{256}
ShowMessage(IntToStr(SizeOf(arr4)));
{1024}
end;
我们倒是可以利用这个原理, 迅速知道多维数组的元素总数:
const
arr:
array[
0..1,
0..2,
0..3]
of Integer =
(((
1,
1,
1,
1), (
2,
2,
2,
2), (
3,
3,
3,
3)), ((
4,
4,
4,
4), (
5,
5,
5,
5), (
6,
6,
6,
6)));
begin
ShowMessage(IntToStr(SizeOf(arr)
div SizeOf(Integer)));
{24}
end;
如何把字符串覆给数组
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{把字符串给静态(字符)数组}
procedure TForm1
.Button1Click(Sender: TObject);
const
str =
'万一的 Delphi 博客';
var
StaticArr:
array[
0..255]
of Char;
begin
{直接赋值即可}
StaticArr := str;
{显示}
ShowMessage(StaticArr);
{万一的 Delphi 博客}
end;
{把字符串给动态(字符)数组}
procedure TForm1
.Button2Click(Sender: TObject);
const
str =
'万一的 Delphi 博客';
var
DynamicArr:
array of Char;
i: Integer;
begin
{设置动态数组大小}
SetLength(DynamicArr, Length(str));
{把字符串赋给动态数组}
for i :=
0 to Length(DynamicArr) -
1 do
DynamicArr[i] := str[i+
1];
{显示动态数组中的字符}
ShowMessage(PChar(@DynamicArr[
0]));
{万一的 Delphi 博客}
end;
{数组元素可不一定都是字符}
procedure TForm1
.Button3Click(Sender: TObject);
const
str =
'万一的 Delphi 博客';
var
DynamicArr:
array of string;
begin
SetLength(DynamicArr,
1);
DynamicArr[
0] := str;
ShowMessage(DynamicArr[
0]);
{万一的 Delphi 博客}
end;
end.
多维动态数组与多维动态数组指针
本例效果图:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1
.FormCreate(Sender: TObject);
begin
Memo1
.Align := alLeft;
end;
{多维动态数组}
procedure TForm1
.Button1Click(Sender: TObject);
var
Arr:
array of array of array of Integer;
{定义一个三维动态数组}
i,j,k,ic,jc,kc: Integer;
begin
{设置数组}
SetLength(Arr,
2,
3,
4);
{获取各维的维数}
ic := Length(Arr);
jc := Length(Arr[
0]);
kc := Length(Arr[
0][
0]);
{赋值}
for i :=
0 to ic -
1 do
for j :=
0 to jc -
1 do
for k :=
0 to kc -
1 do
Arr[i][j][k] := Random(
100);
{取值}
Memo1
.Clear;
for i :=
0 to ic -
1 do
for j :=
0 to jc -
1 do
for k :=
0 to kc -
1 do
Memo1
.Lines
.Add(Format(
'Arr[%d][%d][%d] = %d', [i, j, k, Arr[i][j][k]]));
end;
{多维动态数组指针}
procedure TForm1
.Button2Click(Sender: TObject);
Type
TMyArr =
array of array of array of Integer;
{定义一个三维动态数组类型}
var
PArr: ^TMyArr;
{动态数组指针变量}
i,j,k,ic,jc,kc: Integer;
begin
{用作维数的变量}
ic :=
2;
jc :=
3;
kc :=
4;
{分配内存; 按说动态数组还需要 8 个管理字节, 我不知道 Delphi 是怎么协调的}
GetMem(PArr, ic * jc * kc * SizeOf(Integer));
{设置数组}
SetLength(PArr^, ic,jc,kc);
{赋值}
for i :=
0 to ic -
1 do
for j :=
0 to jc -
1 do
for k :=
0 to kc -
1 do
PArr^[i][j][k] := Random(
100);
{取值}
Memo1
.Clear;
for i :=
0 to ic -
1 do
for j :=
0 to jc -
1 do
for k :=
0 to kc -
1 do
Memo1
.Lines
.Add(Format(
'Arr[%d][%d][%d] = %d', [i, j, k, PArr^[i][j][k]]));
{自己分配的内存要负责释放}
FreeMem(PArr);
end;
end.
数组类型与数组指针的巧妙利用
本例通过存取结构, 慢慢引入了数组类型与指针的一些使用方法; 其中六个小例子的测试内容和结果都是一样的.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
Button6: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type {先定义结构和结构指针}
PMyRec = ^TMyRec;
TMyRec =
record
F1: Char;
F2: Word;
end;
{用静态数组储存或读写结构很方便}
procedure TForm1
.Button1Click(Sender: TObject);
var
ArrRec:
array[
0..2]
of TMyRec;
i: Integer;
begin
{写入}
for i :=
0 to 2 do
begin
ArrRec[i].F1 := Chr(i+
65);
ArrRec[i].F2 := (i+
1) *
10;
end;
{读取}
for i :=
0 to Length(ArrRec) -
1 do
ShowMessageFmt(
'%s, %d', [ArrRec[i].F1, ArrRec[i].F2]);
end;
{这个只是定义了一块内存, 没用数组的概念, 有点麻烦}
procedure TForm1
.Button2Click(Sender: TObject);
var
buf: PMyRec;
begin
GetMem(buf, SizeOf(TMyRec) *
3);
{申请内存}
{写入}
buf^.F1 :=
'A';
buf^.F2 :=
10;
Inc(buf);
{到下一个}
buf^.F1 :=
'B';
buf^.F2 :=
20;
Inc(buf);
buf^.F1 :=
'C';
buf^.F2 :=
30;
Dec(buf,
2);
{回到开始}
{读取}
ShowMessageFmt(
'%s, %d', [buf^.F1, buf^.F2]);
Inc(buf);
{到下一个}
ShowMessageFmt(
'%s, %d', [buf^.F1, buf^.F2]);
Inc(buf);
ShowMessageFmt(
'%s, %d', [buf^.F1, buf^.F2]);
Dec(buf,
2);
{回到开始}
FreeMem(buf);
{释放内存}
end;
{可以给结构定义一个数组类型}
procedure TForm1
.Button3Click(Sender: TObject);
type
TArr =
array of TMyRec;
var
buf: PMyRec;
i: Integer;
begin
GetMem(buf, SizeOf(TMyRec) *
3);
for i :=
0 to 2 do
begin
TArr(buf)[i].F1 := Chr(i+
65);
TArr(buf)[i].F2 := (i+
1) *
10;
end;
for i :=
0 to 2 do
ShowMessageFmt(
'%s, %d', [TArr(buf)[i].F1, TArr(buf)[i].F2]);
FreeMem(buf);
end;
{直接用动态数组也行}
procedure TForm1
.Button4Click(Sender: TObject);
var
Arr:
array of TMyRec;
i: Integer;
begin
SetLength(Arr,
3);
for i :=
0 to 2 do
begin
Arr[i].F1 := Chr(i+
65);
Arr[i].F2 := (i+
1) *
10;
end;
for i :=
0 to 2 do
ShowMessageFmt(
'%s, %d', [Arr[i].F1, Arr[i].F2]);
end;
{使用一个元素的数组指针, 这是很常用的}
procedure TForm1
.Button5Click(Sender: TObject);
type
PArr = ^TArr;
TArr =
array[
0..0]
of TMyRec;
var
buf: PArr;
i: Integer;
begin
GetMem(buf, SizeOf(TMyRec) *
3);
for i :=
0 to 2 do
begin
buf^[i].F1 := Chr(i+
65);
buf^[i].F2 := (i+
1) *
10;
end;
{用这种方法不能像下面这样读写, 也就是 [] 中不能是超过 0 的常数, 但可以用变量}
{这也容易理解, 因为常量会直接编译到代码中, 在没有分配内存以前, 编译器不知道数组会更大}
{要解决这个问题需要用下一个方法}
// buf[0].F1 := 'A';
// buf[0].F2 := 10;
// buf[1].F1 := 'B';
// buf[1].F2 := 20;
// buf[2].F1 := 'C';
// buf[2].F2 := 30;
for i :=
0 to 2 do
ShowMessageFmt(
'%s, %d', [buf[i].F1, buf[i].F2]);
FreeMem(buf);
end;
{使用一个超大的数组指针, Delphi 的 TList 类就是这么干的}
procedure TForm1
.Button6Click(Sender: TObject);
type
PArr = ^TArr;
TArr =
array[
0..100000]
of TMyRec;
{不要担心内存暴涨, 使用时我们只用其指针}
var
buf: PArr;
i: Integer;
begin
GetMem(buf, SizeOf(TMyRec) *
3);
for i :=
0 to 2 do
begin
buf^[i].F1 := Chr(i+
65);
buf^[i].F2 := (i+
1) *
10;
end;
{和上例不同的是, 下面的代码也可以}
// buf[0].F1 := 'A';
// buf[0].F2 := 10;
// buf[1].F1 := 'B';
// buf[1].F2 := 20;
// buf[2].F1 := 'C';
// buf[2].F2 := 30;
for i :=
0 to 2 do
ShowMessageFmt(
'%s, %d', [buf[i].F1, buf[i].F2]);
FreeMem(buf);
end;
end.
复制动态数组
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TArr =
array of Int64;
{先把需要的动态数组数组定义成一个类型, 因为下面需要类型转换}
var
arr1,arr2: TArr;
{两个等待测试的数组变量}
p: Pointer;
{该指针用于中转数组中的数据}
{先给第一个数组赋测试值}
procedure TForm1
.FormCreate(Sender: TObject);
var
i: Integer;
begin
for i :=
0 to 1000 -
1 do
begin
SetLength(arr1, Length(arr1)+
1);
arr1[High(arr1)] := i *
2;
end;
{抽查显示}
ShowMessage(IntToStr(arr1[
9]));
{18}
end;
{复制到第二个数组}
procedure TForm1
.Button1Click(Sender: TObject);
var
size: Cardinal;
begin
size := Length(arr1) * SizeOf(arr1[
0]);
{源数组大小}
GetMem(p, size);
{根据源数组大小分配内存}
CopyMemory(p, arr1, size);
{复制}
arr2 := TArr(p);
{转换}
{抽查显示}
ShowMessage(IntToStr(arr2[
9]));
{18}
end;
end.
假定数组元素是个结构, 再测试一次:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TRec =
record
str:
string;
int: Integer;
end;
TArr =
array of TRec;
var
arr1,arr2: TArr;
p: Pointer;
procedure TForm1
.FormCreate(Sender: TObject);
var
i: Integer;
begin
for i :=
0 to 1000 -
1 do
begin
SetLength(arr1, Length(arr1)+
1);
arr1[High(arr1)].str := IntToStr(i);
arr1[High(arr1)].int := i *
2;
end;
ShowMessageFmt(
'%s,%d',[arr1[
9].str, arr1[
9].int]);
{9,18}
end;
procedure TForm1
.Button1Click(Sender: TObject);
var
size: Cardinal;
begin
size := Length(arr1) * SizeOf(arr1[
0]);
GetMem(p, size);
CopyMemory(p, arr1, size);
arr2 := TArr(p);
ShowMessageFmt(
'%s,%d',[arr2[
9].str, arr2[
9].int]);
{9,18}
end;
end.