数组类型与指针类型.ppt_第1页
数组类型与指针类型.ppt_第2页
数组类型与指针类型.ppt_第3页
数组类型与指针类型.ppt_第4页
数组类型与指针类型.ppt_第5页
已阅读5页,还剩56页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第5章 数组类型与指针类型,5.1 数据类型的构造,*5.3 指针类型,*5.2 数组类型,结束放映,系统预先提供的类型:C语言提供的基本数据类型,大致分为整型、实型、字符型等三大类 用户新定义的类型:C语言提供构造新类型的方法,可以在已有数据类型的基础上构造新的数据类型,这种新的类型称为构造类型,根据构造方法的不同分为数组、指针、结构、联合等四种,5.1 数据类型的构造,5.2 数组类型,为什么要用数组?(重点理解),问题:假如现在班级里有100个人,要求用C语言程序来 实现求这100个人的数学成绩之和,( 想一想怎么写?),使用数组的目的:为了解决这种大量同种类型数据的存储与使用问题,5.

2、2 数组类型,数组类型的定义 数组是由一系列同类型的元素(Element)所组成的集合,数组变量名就一个 数组中元素的数据类型可以是基本类型,也可以是构造类型,若元素的类型是整型则称为整型数组,若元素类型是结构体类型则称为结构体数组,若元素类型是指针类型则称为指针数组,若成员的类型是数组则称为二维数组,一维数组(重点掌握) 当数组中元素的类型不是数组,而是基本类型,或者结构,指针等构造类型时,称为一维数组 一维数组变量的定义的格式(掌握) 元素数据类型 数组变量名常量或数值表达式 注意 常量的值表示了数组的大小即元素的个数,必须为正整型(记住:这里数组的大小一定不能是个变量)。 如果数组大小是

3、个数值表达式的值是小数,一定先取整, int a7/2 即 a3 数组变量名需要符合标识符命名的要求,不能与已有的变量名或系统关键字相同。,方式1:数组只能在定义的同时对数组整体进行赋初值 (而普通变量可以先声明后初始化) 格式: 数据类型 数组变量名元素个数 = 元素1初值,元素2初值,. 初值用一对括起来。相邻的值之间用逗号隔开 例如: int arr10 = 9,8,7,6,5,4,3,2,1,0; 上面定义了一个一维数组 ,名字为arr,共10个元素。元素的类型为int,初始值为从9到0。 以下方式是错误的: int arr10; arr10 =9,8,7,6,5,4,3,2,1,0;

4、/error Arr = 100;/error,问题:前面我们讲了怎样定义一个一维数组的格式,那么定义完了如何给这个一维数组中的每个元素赋值呢?它的赋值方式和一个普通变量的赋值有什么区别?,方式1注意: 使用方式1给数组整体赋值,初值的个数不能超过数组的大小(即可以小于但觉不能大于) int arr10 = 9,8,7 /允许 你这里定义了数组为10个元素,但你可以给它赋少于10个的初始值。但至少有一个,那么那些没有得到初始值的元素的值又是多少呢?他们则被编译器初始化为0,但是如果只定义数组,没有对其进行任何初始化,局部变量则是未定义的值(即不可预测的值),全局变量将被编译器自动初始化为0,方

5、式2:先定义,后初始化时只能针对数组中单个的元素进行赋值,而不能进行整体赋值 例如 int arr10; arr0 = 9; arr1 = 8; . 这里需要访问数组中的每个元素,所以需要使用下标来区分数组中的每个元素,下标只能是整形,C语言规定,访问数组中的元素下标从0开始,即第一个元素是 数组名0,方式3:用一个数组给另一个数组赋值 例如: int a5 = 1,2,3,4,5 int b5 ; 怎样用a初始化数组b呢?想一想怎样用程序实现,能否自行编写出来。(提示:使用for循环实现) 以下是错误的情况: b = a;/error,一维数组的相关操作举例 例 1:要求从键盘输入5个整数并

6、存储到一个数组中。然后将此数组的内容进行打印输出(怎样实现?想一想),#include void main() int a5; int i; for(i=0;i5;i+) printf(please input the %d data: ,i+1); scanf(%d, ,例2 求上一题目中数组a中元素的最大值的下标,并打印输出此下标和对应的元素的值(怎样修改),void main() int maxIndex = 0; int a5 = 1,2,3,4,5; int i; for(i=0;i amaxIndex) maxIndex = i; printf(the maxIndex is %d

7、n,maxIndex); printf(the array max value is %dn,amaxIndex); ,例3 要求实现在一个数组中查找一个值,这个值由用户输入,判断此值是否在数组中(怎样实现),void main() int value; int a5 = 1,2,3,4,5; int i; int flag = 0; scanf(%d, ,例4 要求实现对一个数组元素进行逆序存放(怎样实现) 例如 int a5 = 1,2,3,4,5 逆序存放后内容变成 a5 = 5,4,3,2,1,void main() int a5 = 1,2,3,4,5; int i = 0; int

8、 j = 4; int temp; while(i j) temp = ai; ai = aj; aj = temp; i+; j-; /下面内容请自行编写使用for循环遍历输出数组的内容 ,例5 要求使用选择法对一个数组元素进行从小到大的排序,最后将排序后的结果进行输出(怎样实现?) 例如 int a5 = 5,2,4,3,1 排序后内容变成 a5 = 1,2,3,4,5,void main() int i,j,smallIndex=0; int temp; int a5 = 5,2,4,3,1; for(i=0;i4;i+) smallIndex = i; for(j=i+1;j5;j+)

9、 if(aj asmallIndex) smallIndex = j; temp = ai; ai = asmallIndex; asmallIndex = temp; ,例6 利用数组获得20项Fibonacci数列元素,即后一项为前两项之和,开始两项为1,可得序列为1,1,2,3,5,8, #include void main() int i,f20=1,1; for(i=2;i=19;i+) fi=fi-2+fi-1; for(i=0;i=19;i+) printf(%d/n,fi); ,数组的存储(掌握) 数组的存储涉及两个问题:每个成员要有存储空间且每个成员可以通过下标找到存储空间的

10、位置。 数组的存储方法:分配连续的一块内存区域能够存放得下所有的元素,然后将数组成员按下标顺序连续存放,零号成员存放在这块内存区的最前面,所以数组的实质是内存中一段连续的存储区域,假设内存地址为start,由于每个成员所占的存储空间大小是相同的,假设为m个字节,这时i号成员的内存地址就等于start+m*i。,定义了一个10个元素的int数组,占据的内存空间, 10*4个字节,每4个字节空间就代表着一个元素,数组访问越界问题:,越界?越谁的界?当然是内存。一个变量存放在内存里,你想读的 是这个变量的内存空间,结果却读过头了,很可能读到了另一个变 量的头上。这就造成了越界。 数组的访问越界问题,

11、看如下代码: int arr10,i; for( i=1; i=10; i+) printf(“%d”,arri); ,这里访问数组的元素已经越界了!但是编译器不提示错误,即 编译器不进行数组访问越界的检查。但这明明是个错误,所以 一个隐秘的错误就包含到了你的程序中,这是非常可怕的事,当 程序运行起来后,有可能会出现莫名奇妙的错误。错误表现不定,有问题的代码,数组访问越界问题:,为什么数组访问越界会造成莫名其妙的错误? 前面我们讲过数组的 实质是一段连续的内存空间。然后,我们可以通过指定数组下标来访 问这块内存里的不同位置。因此,当你的下标过大时,访问到的内存 就不再是这个数组“份内”的内存。

12、你访问的,将是其它变量的内存了。 举个例子数组就像一排的宿舍,假设有5间,你住在第2间; 如果你晚上喝多了,回来时进错了房间,只要你进的还是这5间, 那倒不会有大事,可是若是你“越界”了。竟然一头撞入第6间 这第6间会是什么?很可能它是走廊的尽头,结果你一头掉下楼, 这在生活中很不幸,可对于程序倒是好事了,因为错误很直接 (类似直接死机),你很容易发现。可是, 如果第6间是?据我所知,第6间可能是厕所,也可能是女生宿舍。 所以数组访问下标越界问题,程序会表现出不可预知的错误。,这个问题:怎样解决?,数组与指针变量(掌握) 数组名是数组中第一个元素的内存地址即首地址,是地址。 指针变量是存放某种

13、类型变量地址的变量,所以指针变量能保存数组的首地址,那么这时指针变量就指向了这个数组 前面已经介绍了使用下标访问数组元素,使用指针变量也可以访问数组元素。分为两步: (1)建立指针变量,取得数组中第一个元素的地址; (2)重复通过指针加1来获得下一个数组元素的指针。 第一步获取指针可以通过两种方式一种是利用取址运算( /*通过*定义指针变量p/ p= ,注意:p-2中的2是地址偏移量,表示p的内容-2个元素大小的内存空间,例 有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。a数组已经按照从小到大的顺序排列好,加入数保持有序的方法是先将所有大于该数的元素后移一格,再将该数放

14、到这些数的前面。,新元素X,程序如下: #include void main() int a11=1,4,6,9,13,16,19,28,40,100; int i,number; printf(original array is:n); for(i=0;i=0;i-) if(ainumber) ai+1=ai; else break; ai+1=number; for(i=0;i11;i+) printf(%5d,ai); printf(n); ,一维数组作为参数(掌握) 一维数组实参采用地址传递方式,提供给形参的不是数组的所有元素值,而是一个简单的数组零号元素的地址。 通过形参中的地址可以

15、找到一维数组实参的所有元素的存储空间,函数中可以直接访问这些元素空间。 为了函数可以检查越界错误,可以将数组大小作为函数参数一并传递。 形参定义方式可以是一维数组定义形式,也可以省略定义中的数组大小,还可以直接定义为指针类型,这三种方式含义是一样的。 调用函数时提供的一维数组实参就是待传递数组的第一元素的地址,一般直接将数组名作为实参。,例 编写一个函数实现将一维数组的内容倒置,该功能前面已进行过讲解,请自行写一下试一试,【例5.8】编写一个自定义函数可以查找任意数组中是否存在一个特定数据。 #include int search(int s10 , int x) int i ; for(i=

16、0;i10;i+) if(si=x) break; if(i10) return 1; else return 0; void main() int a10,i, e; printf(Enter the array :n); for(i=0; i10;i+) scanf(%d, ,二维数组(理解)具有两个下标的数组称为二维数组 通常,二维数组可看成是数学中的矩阵,因此,习惯上将第一维下标称为行标,第二维下标称为列标。 二维数组变量的定义:元素类型 数组名常量表达式1常量表达式2=初始值表; 说明: 元素类型是构成数组的数据成员的类型。 常量表达式1和常量表达式2分别代表行标和列标的大小,它们均

17、从0开始。,二维数组实质:我们可以把一个二维数组a看作是一种特殊的一维数组,而这个一维数组的元素又是一个一维数组。例如a34 a0=a00,a01,a02,a03 a1=a10,a11,a12,a13 a2=a20,a21,a22,a23 a0,a1,a2分别是三个一维数组的数组名,实际的二维数组存储也是按一维数组的存储方式存储的。这里的二维数组默认按照行的顺序存储,二维数组变量的初始化 (1)按维给二维数组赋初值,(推荐使用,清楚直观)例如:int A34=1,2,3,4,5,6,7,8,9,10,11,12; (2)可以将所有数据写在一个花括号内,按存放顺序连续赋初值(此方法编程中不推荐使

18、用) 例如:int A34=1,2,3,4,5,6,7,8,9,10,11,12; (3)如果能提供所有数组元素的初始值,则定义数组时只需要提供第二维大小,第一维可以省略 例如:int A4=1,2,3,4,5,6,7,8,9,10,11,12;,二维数组的基本操作举例 【例5.11】编程将矩阵A转置后存放到矩阵B中,即Bji=Aji。 #include void main() int A34,B43,i,j; for(i=0;i3;i+) for(j=0;j4;j+) scanf(“%d”, ,字符数组与字符串(重点掌握) 字符串常量字符串常量使用双引号界定,字符串常量的存储是采用连续的字符

19、后跟一个结束标志零(即字符0)的方法,这样,提供一个字符串只需提供该串的串首指针(地址)即可 示例:C Language在内存保存的情况如下,字符串变量字符串变量C语言中不能直接定义,需要通过使用字符数组来模拟定义,通常的方法有两种。(1)字符数组变量法例如:char str=“C Language”;/由系统计算长度 (2)字符指针变量法例如:char *str=C Language; 说明:1)要使用该数组中的每个字符,可以使用下标运算 来完成。2)字符数组常被作为一个整体,看作字符串变量来使用,为便于操作,提供了一批字符串函数对其处理。3)字符串常量和字符串变量名实质上只提供了字符串的首

20、地址,它们参加的各种运算实际上是一种指针性质的运算。,要求实现一个让字符串倒序存放的功能说明:字符串倒序是将串中字符左右颠倒,如abc则变成cba。(此题的解题方法在一维数组部分已讲解过能否自行实现?) #include void main() char str=The quick brown fox jumps over the lazy dog.; int i = 0,n; char temp; n=sizeof(str)-1;/*字符个数*/ while(in)temp=stri;stri=strn;strn=temp;i+;n-; printf(%sn,str);,字符串做函数参数 【

21、例5.19】求字符串长度(长度不包括0) #include int mystrlen(char *s) int i; for(i=0;*s!=0;s+,i+);/知道0在字符串中的作用了吗? return i;void main() char str=Computer Science; printf(%dn,mystrlen(str);,【例5.20】比较两个字符串的大小#include int mystrcmp(char *s1,char *s2) for(;*s1!=NULL,字符串的标准函数(string.h)(会使用以下库函数) 1strlen函数其函数原型为: int strlen(

22、 char * s);其功能是:根据字符指针s所指向的字符串(提供的字符序列要以0结尾),返回其中字符个数。 2strlwr函数其函数原型为: char * strlwr(char * s);其功能是:将字符指针s所指向的字符串中所有字母均变成小写字母,将该串的首地址作为字符指针返回。,3strupr函数其函数原型为:char * strupr(char * s);其功能是:将字符指针s所指向的字符串中所有字母均变成大写字母,将该串的首地址作为字符指针返回。 4strcmp函数其函数原型为: int strcmp(const char * s1,const char * s2);其功能是:将字

23、符指针s1和s2所指向的字符串进行比较,如果对应的每个字符均相同而且长度也相等,则函数返回0,否则以不相同位置的字符的ASCII码相减,返回差,其规律为:(1)返回值0,表示s1串大于s2串。(2)返回值0,表示s1串小于s2串。,5strcpy函数其函数原型为: char * strcpy(char * dest,const char * src);其功能是:将字符指针src所指向的串复制到dest所指向的字符型内存空间中,并且将dest串的首地址作为字符型指针返回。 6strcat函数其函数原型为: char * strcat(char * dest,const char * src);其

24、功能是:将字符指针src所指向的串连接到dest所指向的字符串的后面的剩余内存空间中,并且将目的串dest的首地址作为字符型指针返回。,7strstr函数 其函数原型为: char * strstr(const char * s1,const char * s2); 功能是:在字符指针s1所指向的串中查找s2所指向的字符串是否出现,若s2串在s1串中出现了,则返回在s1中出现的位置指针,否则返回NULL指针。,5.3 指针类型,1、什么是指针指针就是地址。C语言将这种地址也看成是数据,有直接使用和间接使用两种使用方法。 直接使用:直接使用地址本身,得到结果仍是指针。 间接使用:通过地址找到内存

25、中的单元,然后访问该单元。 2、什么是指针变量是用于保存地址的变量。,下图例示指针变量与一般变量的区别,指针的表示 指针变量的定义基类型* 指针变量名=初始化值; 说明:基类型是指针所指向的内存单元的类型。指针变量名前面必须通过*号标识,不能与保留字和其它变量同名。初始化值是内存单元的地址,该内存单元必须是基类型,省略时指针变量中为随机值。NULL是空指针常量,值为零,可以作为作为指针变量的初值。,示例:指针变量的合法的定义形式:int *p1;float *p2;int i,j,*p3=,指针的操作 指针的操作有两类:直接使用指针本身作为数据值进行操作得到的结果仍然是指针,间接使用指针访问指

26、针所指向的内存单元得到的结果是内存单元的值。 指针的直接操作 取址与赋值:。,指针的间接操作间接操作指针是指通过指针访问所指向的内存单元的过程具体步骤如下: 1)先通过指针的直接操作计算得到内存单元的地址 2)再通过间接访问运算符*访问该地址所指向的内存单元, 例如,int i, *p1=,指针的使用 (1) 1) *p整型指针变量p初始化时赋值为一维数组名A,即A数组中第一元素A0的地址,*p的结果是间接访问p所指向内存单元,即A0。 2) *(p+i)同上,p的结果是A0的地址,p+i的作用是调整指针,结果是数组元素A0后面排在第i个位置的数组元素的地址,即Ai的地址,*(p+i)的结果是

27、间接访问指针p+i所指向的内存单元Ai。,再看几个示例: int A10, *p=A, *q, i=5; 3) q=语句后如前3)所述,指针变量q通过赋值得到了A5的地址,q+的结果是q加1之前的地址值,仍然是A5的地址,*(q+)的结果是间接访问指针q+所指向的内存单元A5。最后指针变量q会由于+运算增1指向A6的地址,但这不会影响*(q+)的结果。,再看几个示例: int A10, *p=A, *q, i=5; 5) *(+q) 当执行q=语句后如前3)所述,指针变量q通过赋值得到了A5的地址,+q的结果是修改q,使指针变量q加1,这时q指向A5的下一个单元A6,所以结果是A6的地址,*(

28、+q)的结果是间接访问指针+q所指向的内存单元A6。 6) *(A+i)数组名A表示了数组中第一元素的地址,即A0的地址,A+i是指针操作,结果是数组中A0元素之后排在第i个位置的数组元素的地址,即Ai的地址,*(A+i)的结果是间接访问指针A+i所指向的内存单元Ai。,再看几个示例: int A10, *p=A, *q, i=5; 7) pi指针变量名p后跟下标操作是一种合法的操作,表示间接访问指针p+i所指向的内存空间,由于p初始化为A0的地址,p+i的结果是A0后第i个数组成员Ai的地址,因此,pi的结果是间接访问数组成员Ai。,指针作为参数 地址传递方式是将实参指针赋值给形参指针变量,形参指针变量和实参指针所指向的内存单元是同一个,通过间接访问形参指针变量就能使用该内存单元,数组类型的函数参数采用这种传递方式。 使用指针变量作为函数参数可以修改主程序中的内存单元,通过这种方式可以使函数返回

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论