Delphi - 数组 详解
技术交流,DH讲解.
首先我们要知道什么是数组?数组是一堆相同特性数据的一个集合,也就是每个元素的类型必须是一样的,当然在其他一些弱语法的语言里面,数组的元素可以千奇百怪.
例子:
1
2
3
4
5
6
|
Var A: Array [ 0..2 ] Of Integer ; Begin A[ 0 ] := 1 ; A[ 1 ] := 1.0 ; //这里是错的,因为每个元素都必须是Integer类型 End ; |
Delphi中数组分类:
1 定长和不定长.
定长数组:也就是长度在声明的时候就确定了,后面是不能改变的,而在定长数组中,起始序号不必从0开始,可以自己定.例如:
1
2
3
4
5
6
|
Var A: Array [ 2..3 ] Of Integer ; Begin A[ 2 ] := 1 ; SetLength(A, 3 ); //这里会出错,定长数组不能再分配 End ; |
从上面我们可以看到起始序号是2,但是步长是1,是不能改变的.为什么我们看到很多数组的起始序号都是0呢?习惯而已.大家都习惯在厕所里面去嘘嘘,而你一个人习惯在广场上面嘘嘘,那么大家都会说你不文明了.但是如果大家一开始都是在广场上面嘘嘘的话,不说了太恶心了.
来看一个特殊的用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
type THuangJacky = (hjA,hjB,hjC); const //用法1 B: array [ 0..2 ] of string = ( 'A' , 'B' , 'C' ); //用法2 C: array [THuangJacky] of string = ( 'A' , 'B' , 'C' ); Var H:THuangJacky; S: string ; Begin S:=B[Ord(H)]; S:=C[H]; //B[H] 和 C[1]都会出错 End ; |
用法1 和用法2你觉得那种用着爽一些?
从上面例子可以看出来只要是序数类型都可以当数组的序号.但是我们用的时候序号就必须是声明的那种序数类型,所以上面代码注释中才会写出2种错误的情况.
不定长数组:动态数组,也就是声明的时候没有说长度是多少,在使用前必须声明,长度可以再分配.序号必须从0开始.看个简单的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Var A: Array Of Integer ; Begin SetLength( A, 3 ) ; //数组一共有3个元素 A[ 0 ] := 1 ; A[ 1 ] := 2 ; A[ 2 ] := 3 ; //A[3]没有它,有它的话,你数一下几个了?不会数数,那我推荐你去街道口小学看一下 SetLength( A, 4 ) ; //如果变长长度,直接增加后面的元素 A[ 3 ] := 4 ; //现在有它了. SetLength( A, 3 ) ; //如果长度变短,超出部分会被去掉 // A[3]又没有它了 End ; |
有时候大家这样要先设定长度,然后再赋值,是不是很麻烦?没有一气呵成的感觉.好吧,再说一招:
1
2
3
4
5
6
7
8
9
|
Type TA = Array Of Integer ; Var A: TA ; Begin A := TA . Create( 1 , 2 , 3 ) ; //此招请勿在D7上面使用 //这样A[0]:=1,A[1]:=2,A[2]:=3 End ; |
2 一维和多维.
前面所有例子,我们都只是说了一维数组,要是现在我们想弄一个矩阵(多维数组)怎么办?
1
2
3
4
5
6
7
|
Var A: Array [ 0 .. 2 , 0 .. 2 ] Of Integer ; B: Array [ 0 .. 2 ] Of Array [ 0 .. 2 ] Of Integer ; Begin A[ 0 , 0 ]:= 1 ; A[ 0 ][ 0 ]:= 1 ; End ; |
两种方法都可以的.
1
2
3
4
5
6
7
8
9
10
|
Var B: Array Of Array Of Integer ; Begin SetLength(B, 3 , 3 ); // 3*3矩阵 // 如果要实现齿状数组,必须这么做 SetLength(B, 3 ); SetLength(B[ 0 ], 1 ); // * SetLength(B[ 1 ], 2 ); // ** SetLength(B[ 2 ], 3 ); // *** End ; |
接下来我们说说几个关于数组中常用的函数:
第一个 复制数组
1
2
3
4
5
6
7
8
9
|
Var A, B: Array [ 0 .. 1 ] Of Integer ; Begin A[ 0 ]:= 1 ; A[ 1 ]:= 2 ; B:= A; B[ 0 ]:= 2 ; ShowMessageFmt( 'A0:%D,B0:%D' , [A[ 0 ], B[ 0 ]]); // A0:1,B0:2 End ; |
这个效果就是我们想要的,貌似没有什么好说的.如果是动态数组呢?
1
2
3
4
5
6
7
8
9
10
11
|
Var A, B: Array Of Integer ; Begin SetLength(A, 2 ); SetLength(B, 2 ); A[ 0 ]:= 1 ; A[ 1 ]:= 2 ; B:= A; B[ 0 ]:= 2 ; ShowMessageFmt( 'A0:%D,B0:%D' , [A[ 0 ], B[ 0 ]]); // A0:2,B0:2 End ; |
现在怎么办?A和B被关联到了一个地址了,其实现在我们可以使用Copy函数,对就是复制字符串的那个函数:
1
2
3
4
5
6
7
8
9
10
11
12
|
Var A, B: Array Of Integer ; Begin SetLength(A, 2 ); SetLength(B, 2 ); A[ 0 ]:= 1 ; A[ 1 ]:= 2 ; B:= Copy(A); // 整个数组都复制过去 B:= Copy(A, 0 , 2 ); // 选择性复制 B[ 0 ]:= 2 ; ShowMessageFmt( 'A0:%D,B0:%D' , [A[ 0 ], B[ 0 ]]); // A0:1,B0:2 End ; |
第二个 序号相关
函数Low()和High()值得信赖,不过我们需要注意的是,它们返回的类型是我们数组的序号的那个类型,并不都是Integer,如前面例子中的THuangJacky.
1
2
3
4
5
6
7
8
9
10
11
12
|
var A : array of array of string ; I, J : Integer ; begin SetLength(A, 10 ); for I := Low(A) to High(A) do begin SetLength(A[I], I); for J := Low(A[I]) to High(A[I]) do A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ' ; end ; end ; |
第三个 数组长度
Length()函数返回的就一定是是Integer了,因为个数不是整数难道还有半个么?
1
2
3
4
5
6
|
Var A: Array Of Integer ; Begin SetLength(A, 2 ); Length(A); // 返回2 End ; |
1
|
|
最后说个问题我就不说了:
从上面那个复制的例子我们可以看出来什么东西?
定长数组变量就是一个变量,所以可以直接用:=来赋值,而动态数组变量就是一个指针,如果用了:=来赋值2个变量就关联在一起了.
1
2
3
4
5
6
7
8
|
Var A: Array [ 0 .. 2 ] Of Integer ; B: Array Of Integer ; Begin ShowMessageFmt( 'A:%8x,A[0]:%8p' , [ Integer (@A), @A[ 0 ]]); // 一样,从地址来看这个数组空间在栈上面 SetLength(B, 3 ); ShowMessageFmt( 'B:%8p,B[0]:%8p' , [B, @B[ 0 ]]); // 一样,这个数据空间在堆上面 End ; |
我们看到A要取地址才和A[0]取地址一样,那么也就是说A就是A[0].
而B直接就和B[0]取地址一样了,也就是说B就是B[0]的地址.
数组在内存中的分布:连续分布的,间隔就是每个元素的大小.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Var A: Array [ 0 .. 2 ] Of Integer ; B: Array Of Integer ; Begin A[ 1 ]:= 123 ; // 从A也就是A[0]的地址上面 往下走4个直接 就是A[1] ShowMessageFmt( 'A[1]:%D,直接取值:%D' , [A[ 1 ], PInteger( Integer (@A)+ 4 )^]); // 一样,都是123 SetLength(B, 3 ); B[ 2 ]:= 88 ; // 从B往下走8个字节就是B[2] ShowMessageFmt( 'B[2]:%D,直接取值:%D' , [B[ 2 ], PInteger( Integer (B)+ 8 )^]); // 一样,88 End ; |
但是动态数组的结构和字符的结构就很像了:
偏移 | -8 | -4 | 0~Length*元素大小-1 |
内容 | 32位引用次数 | 元素个数 | 实际内容 |
SetLength: 设定数组长度
SetLength(MyArray, 5) // 设定MyArray数组长度为5
High: 传回注脚的最大值,如果参数为数组类型的话,则是返回数组索引的最大值
High(MyArray) // 返回值为5
Copy: 字符串截取函数
Copy('substring', 4, 3) // 返回值为‘str’
Delphi - 数组 详解的更多相关文章
- Delphi指针详解
Delphi指针详解2007-12-04 06:08:57| 分类: DLL学习 阅读91 评论0 字号:大中小 订阅 大家都认为,C语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用 ...
- Delphi 关键字详解
Delphi 关键字详解[整理于 "橙子" 的帖子] absolute //它使得你能够创建一个新变量, 并且该变量的起始地址与另一个变量相同. var Str: ]; S ...
- 3.awk数组详解及企业实战案例
awk数组详解及企业实战案例 3.打印数组: [root@nfs-server test]# awk 'BEGIN{array[1]="zhurui";array[2]=" ...
- JavaScript进阶(十)Array 数组详解
JS array 数组详解 数组的声明方法 arrayObj = new Array(); 的数组 ,并且第一位是5 数组的运算(传地址) var t2=new Array(); t2[0]=1; t ...
- Java基础之 数组详解
前言:Java内功心法之数组详解,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 数组概念 同一种类型数据的集合.其实数组就是一个容器. 数组 ...
- “全栈2019”Java第三十一章:二维数组和多维数组详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第三十章:数组详解(下篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十九章:数组详解(中篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十八章:数组详解(上篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
随机推荐
- mysql 归档方案(一次性)
一. 归档流程: 1. 导出需要的数据 2. 创建临时表table_tmp 3. 导入数据到临时表 4. 修改原始表名为table_bak 5. 修改临时表为原始表名 二.归档方式对比 1. sele ...
- 【一键激活win8.1系统】
下载激活工具地址: 链接:https://pan.baidu.com/s/1AUaQQRcqfCYWK94KapYjjA 密码:i4sk 下载后,右键单击“以管理员身份运行”Microsoft Too ...
- vue实践---vue结合 promise 封装原生ajax
有时候不想使用axios这样的外部依赖,想自己封装ajax,这里有两种方法 方法一,在单个页面内使用 封装的代码如下: beforeCreate () { this.$http = (() => ...
- Ant自己主动编译打包&公布 android项目
Eclipse用起来尽管方便,可是编译打包android项目还是比較慢,尤其将应用打包公布到各个渠道时,用Eclipse手动打包各种渠道包就有点不切实际了,这时候我们用到Ant帮我们自己主动编译打包了 ...
- Linux 服务器上建立用户并分配权限
查看用户 whoami #要查看当前登录用户的用户名 who am i #表示打开当前伪终端的用户的用户名 who mom likes who 命令其它常用参数 参数 说明 -a 打印能打印的全部 - ...
- 1 了解Scala
1 定义变量 单个变量:var name = "benxintuzi" 等价于 var name : String = "benxintuzi"(即定义变量时 ...
- javascript修改图片链接地址
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> < ...
- ACM暑假集训第三周小结
这一周学的图论,学了这么些 两种存图的方法:邻接矩阵( map[n][n] ) , 邻接表( headlis[n] , vector<int> G[n] )存图的方法,各有各的好,我的理解 ...
- 论JavaWeb前后端分离放弃jsp
1.静态资源使用Nginx反向代理Tomcat,Tomcat挂了网站仍可访问.2.静态与后端服务器分离,提升性能.3.大并发情况下,可同时扩展前后端服务器.4.接口可复用至App相关服务.5.网站热部 ...
- 九度OJ 1343:城际公路网 (最小生成树)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:445 解决:178 题目描述: 为了加快城市之间的通行和物资流动速度,A国政府决定在其境内的N个大中型城市之间,增加修建K条公路.已知这N个 ...