Delphi之动态数组Word下载.docx
- 文档编号:4739814
- 上传时间:2023-05-04
- 格式:DOCX
- 页数:12
- 大小:23.44KB
Delphi之动态数组Word下载.docx
《Delphi之动态数组Word下载.docx》由会员分享,可在线阅读,更多相关《Delphi之动态数组Word下载.docx(12页珍藏版)》请在冰点文库上搜索。
这样就把数组所有值设置为0。
完成这段代码你马上就能读写数组元素的值,而不用害怕内存出错,当然条件是你没有试图访问超过数组上界的元素。
为了更好地初始化,程序中添加了一个按钮,执行数组元素赋值操作:
procedureTForm1.btnFillClick(Sender:
varI:
Integer;
beginforI:
=Low(Array1)toHigh(Array1)doArray1[I]:
=I;
Grow按钮用于修改数组大小,但并不影响数组内容。
单击Grow按钮后,你可以用Getvalue按钮进行检验:
procedureTForm1.btnGrowClick(Sender:
begin//growkeepingexistingvaluesSetLength(Array1,200);
procedureTForm1.btnGetClick(Sender:
begin//extractCaption:
=IntToStr(Array1[99]);
Alias按钮的OnClick事件代码稍复杂些,程序通过:
=算子把一个数组拷贝给另一个数组,从而有效地创建了一个别名(一个新变量,但引用内存中同一数组)。
从中可见,如果你改变了其中一个数组,那么另一个同样也会改变,因为它们指向同一个内存区:
procedureTForm1.btnAliasClick(Sender:
begin//aliasArray2:
=Array1;
//changeone(bothchange)Array2[99]:
=1000;
//showtheotherCaption:
在btnAliasClick事件中增加了两部分操作内容。
第一部分是数组等同测试,不过并不是测试实际的数组元素,而是测试数组所引用的内存区,检测变量是不是内存中同一数组的两个别名:
begin...ifArray1=Array2thenBeep;
//truncatefirstarrayArray1:
=Copy(Array2,0,10);
btnAliasClick事件的第二部分内容是调用Copy函数。
该函数不仅把数据从一个数组移到另一个数组,而且用函数创建的新数组取代第一个数组,结果变量Array1所引用的是11个元素的数组,因此,按Getvalue和Setvalue按钮将产生一个内存错误,并且触发一个异常(除非你把范围检查range-checking选项关掉,这种情况下,错误仍在但屏幕上不会显示异常)。
虽然如此,Fill按钮仍能正常工作,因为需要修改的数组元素由数组当前的下标范围确定。
自从有了动态数组,链表除了在教科书里出现外,已经很少在实际编程中被使用了,事实也是如此,数组的确比传统链表快得多,而且也方便的多。
从Delphi4起,开始了内建各种类型的动态数组支持。
但是,对我们来说动态数组支持似乎做的不够彻底,因为Delphi竟然连删除、插入、移动连续元素的函数都没有提供,让人使用起来总觉得不够爽!
!
J。
作为一名程序员,我们当然要有自己解决问题的能力,下面就让我们简单介绍一下Delphi下的动态数组。
在Delphi中,数组类型有静态数组(a:
array[0..1024]ofinteger)、动态数组(vara:
arrayofinteger)、指针数组(即指向静态数组的指针)和开放数组(仅用于参数传递)。
静态数组、指针数组有速度快的好处,动态数组有大小可变的优势,权衡之下就有了折衷的办法,那就是定义的动态数组在必要时转换为指针。
动态数组声明之后,只有下面几个函数可:
1.设置数组大小,可以任意缩减或增加数组大小
ProcedureSetLength(varS;
NewLength:
integer);
2.取出连续元素,复制给另一个数组变量
FunctionCopy(s;
Index,Count:
integer):
array;
3.取得数组大小及上下限
FunctionLength(s):
integer;
FunctionHigh(x):
FunctionLow(x):
值得注意的是,不加const或var修饰的动态数组会被作为形参传递,而动态数组用const修饰并不意味着你不能修改数组里的元素(不信你可以字自己在程序中试试。
还有一点是High函数调用了Length函数,所以我们在获取数组上限时最好直接用Length(s)函数。
动态数组在内存空间中占用4个字节.
动态数组在内存中的分配表如下:
偏移量
内容
-8
32-bit引用计数
-4
32-bit数组长度
0..数组长度*(元素尺寸)-1
数组元素
元素尺寸=Sizeof(元素类型)
根据上面的分配情况,可以得到如下结果:
如果我们想要清空一个动态数组只需要把“数组长度”和“引用计数”清空即可。
”引用上面的一句话就是:
“权衡之下就有了折衷的办法,那就是定义的动态数组在必要时转换为指针。
”下面是清空动态数组的函数:
procedureDynArraySetZero(varA);
var
P:
PLongint;
//占用4个字节,正好符合32位内存排列
begin
P:
=PLongint(A);
//指向A的地址
Dec(P);
//P地址偏移量是sizeof(A),指向了数组长度
P^:
=0;
//长度清空
//指向引用计数
//计数清空。
上面的函数就这么简单,而且效率也非常高。
下面让我们再来看看怎样删除动态数组中的元素,函数体如下:
{************************************
A变量类型
,elSize=SizeOf(A)
index开始删除的位置索引,Count删除的数量
****************************************}
procedureDynArrayDelete(varA;
elSize:
Longint;
index,Count:
Integer);
len,MaxDelete:
P:
//4个字节的长整形指针
//取的A的地址
ifP=nilthen
Exit;
{
下面这句完全等同于Dec(P);
len:
=P^
因为Dec(P)=Pchar(P)–4
同样是移动4字节的偏移量,只不过后者按字节来移动
}
len:
=PLongint(PChar(P)-4)^;
//变量的长度,偏移量-4
ifindex>
=lenthen//要删除的位置超出范围,退出
MaxDelete:
=len-index;
//最多删除的数量
Count:
=Min(Count,MaxDelete);
//取得一个较小值
ifCount=0then//不要求删除
Dec(len,Count);
//移动到要删除的位置
MoveMemory(PChar(P)+index*elSize,PChar(P)+(index+Count)*elSize,(len-index)*elSize);
//移动内存
//移出“数组长度”位置
//移出“引用计数”位置
//重新再分配调整内存,len新的长度.Sizeof(Longint)*2=2*Dec(P)
ReallocMem(P,len*elSize+Sizeof(Longint)*2);
Inc(P);
//指向数组长度
=len;
//newlength
//指向数组元素,开始的位置
PLongint(A):
=P;
对上面的例子,我们需要注意的是elSize参数,它必须是SizeOf(DyArray_Name),表示元素所占用的字节数。
相信看了上面的例子后,对于动态数组的拷贝,移动想必也可以自己实现了吧J
后续:
其实,Delphi对许多类型的内存分配都很相似,比如string类型,其实它和动态数组是很相似的,我们完全可以把它拿来当成动态数组。
实质上string是Pchar的简易版本。
不管怎么说,了解一些内存的分配对我们这些开发人员来说还是有一些好处的。
动态数组之参数传递
初用Delphi中的动态数组时,有些迷惑.
1、动态数组是指针吗?
动态数组通常会表现出指针功能,先看下面的例子:
procedureDymArrTest();
A,B:
SetLength(A,3);
A[0]:
B:
=A;
B[0]:
=1;
ShowMessage(IntToStr(A[0]));
在以上程序中,A、B数组指向的是相同的地址,所以改变了B[0],结果A[0]会等于1。
虽然动态数组暗含指针功能,但它的内存管理却是生存期管理类型,无需手工释放。
2、为什么改变形参却没有改变实参的值?
虽然动态数组会表现出指针的功能,在直接用它声明形参,改变形参值时,却是不会改变实参的,看下面的例子:
procedureDymArrParam(Arr:
arrayofInteger);
I:
forI:
=0toLength(Arr)-1do
Arr[I]:
=2;
A:
SetLength(A,2);
=0toLength(A)do
A[I]:
DymArrParam(A);
//试图把数组中的元素值改变为2
Caption:
=IntToStr(A[0])+'
'
+IntToStr(A[1]);
可以看到最终并没有把实参数组A元素值变为2。
原因是这种传递方法编译器会在DymArrParam中复制了一个A的副本,而不是像在第1点中所期望的那样改变了A的值,可见动态数组并非就等同指针。
3、如何通过动态数组的形参改变实参值?
1>
在Delphi中很显然方法的是,在DymArrParam过程中通过var修饰形参,即
procedureDymArrParam(varArr:
在不想通过形参改变实参值时,可以用const修饰形参,明确表示出不可修改意思,即
procedureDymArrParam(constArr:
这样做之后,如果对Arr赋值的话,将会编译不通过。
2>
type
另一种就是用type重新定义一个类型,
例如:
TDymIntArray=arrayofInteger;
//在system单元已经声明了个TBoundArray,用它也可以
然后用于形参声明,如下:
TDymIntArray);
调用此函数时用的实参的类型也必须为TDymIntArray。
这样做,不用var修饰形参,也一样可以通过形参改变实参。
在这种情况下,即使用const修饰形参,也一样可以修改形参的值来改变实参的值。
delphi动态数组的使用
动态数组的使用
//例1:
StrArr:
arrayofString;
//动态数组定义时不与维数
SetLength(StrArr,6);
//分配6个元素位置:
0-5
StrArr[0]:
='
万一'
;
//动态数组的下界是0
ShowMessage(StrArr[0]);
//分配空间后和静态数组一样使用
StrArr:
=nil;
//一般没必要手动释放,动态数组离开作用域会自释放
--------------------------------------------------------------------------------
//例2.动态数组的引用:
Arr1,Arr2:
a:
array[0..1]ofInteger;
SetLength(Arr1,6);
Arr1[5]:
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:
//释放其中一个指针,数组继续存在
//例3.数组Copy<
:
=Copy(Arr1);
//数组Copy
//改变Arr2不再影响Arr1
ShowMessage(IntToStr(Arr1[5]-Arr2[5]));
//1
SetLength(Arr1,7);
ShowMessage(IntToStr(Length(Arr1)));
//7
//6,没有一点牵扯了
//例4.数组Copy<
i:
fori:
=Low(Arr1)toHigh(Arr1)do//给每个元素赋值
Arr1[i]:
=i+1;
=Copy(Arr1,1,3);
//只Copy第2..4个元素
ShowMessage(IntToStr(Arr1[1]));
//2,现在Arr2[0]和Arr1[1]的值是一样的
ShowMessage(IntToStr(Arr2[0]));
//2
//6,维数肯定不一样了
//3
//例5.动态多维数组:
Arr:
arrayofarrayofInteger;
//定义多维数组
SetLength(Arr,5,5);
//分配空间
Arr[0,3]:
//赋值
ShowMessage(IntToStr(Arr[0,3]));
//取值
//例6.另类建立:
Arr:
=varArrayCreate([0,3],varInteger);
ShowMessage(IntToStr(Length(Arr)));
=VarArrayOf([1,2,3,4]);
ShowMessage(IntToStr(Arr[0]));
{这是给变体数组使用的,可能会有效率问题}
数组的表达:
A:
arrayofarrayofstring;
I,J:
SetLength(A,10);
forI:
=Low(A)toHigh(A)do
SetLength(A[I],I);
forJ:
=Low(A[I])toHigh(A[I])do
A[I,J]:
=IntToStr(I)+'
+IntToStr(J)+'
'
{赋值}
=0toic-1do
forj:
=0tojc-1do
fork:
=0tokc-1do
//Arr[i][j][k]:
=Random(100);
Arr[I,J,K]:
=RandomRange(100,10000);
//两句表达都可以。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Delphi 动态 数组
![提示](https://static.bingdoc.com/images/bang_tan.gif)