第4章指针与数组

上传人:痛*** 文档编号:163851834 上传时间:2022-10-23 格式:PPT 页数:113 大小:2.38MB
收藏 版权申诉 举报 下载
第4章指针与数组_第1页
第1页 / 共113页
第4章指针与数组_第2页
第2页 / 共113页
第4章指针与数组_第3页
第3页 / 共113页
资源描述:

《第4章指针与数组》由会员分享,可在线阅读,更多相关《第4章指针与数组(113页珍藏版)》请在装配图网上搜索。

1、第第4章章 指针与数组指针与数组第一节第一节 一维数组一维数组第二节第二节 二维数组二维数组第三节第三节 字符数组与字符串字符数组与字符串第四节第四节 指针数组指针数组指针小结指针小结C语言程序设计语言程序设计 龙昭华主编1/113课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)2/113 迄今为止,我们使用的都是属于基本类型,如:整型、字符型、实型等类型的数据。而C还提供了构造类型,如:数组类型、结构体类型、公用体类型等。构造类型数据是由基本类型数据按一定规则组成的,因此有些书称它们为“导出类型”。在程序设计中

2、,常常需要处理大量同类型的相关数据,如每个学生的成绩记录,多个相同类型数据的排序等。这类数据在计算机语言中可以通过数组来表示。所谓数组数组就是具有相同数据类型的有序集合。在C语言中,数组具有以下几个特点:数组的所有元素使用一个共同的名字,称为数组名数组名,数组名使用标识符来表示。每个数组元素的使用由数组的下标来确定。数组元素的个数必须在定义时确定,程序中不可改变。在C语言中,数组下标是从0开始,到数组元素个数减1结束的。同一数组中的每一元素具有相同的数据类型相同的数据类型(可以是基本类型或构造类型等)。同一数组在内存中占据一段连续的存储单元连续的存储单元。数组中元素的作用相当于简单变量。数组必

3、须先定义后使用。课件制作:刘达明课件制作:刘达明 023-66834110一、一、一维数组的定义和引用一维数组的定义和引用第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)3/1131 1、一维数组的定义、一维数组的定义 一维数组是指只有一个下标的数组元素所组成的数组。一维数组的定义方式为:类型说明符类型说明符 数组名数组名 常量表达式常量表达式;例如:int a10;它表示数组名为a,此数组有10个元素,分别为a0、a1、a2、a3、a4、a5、a6、a7、a8、a9。又如:存放30个学生的数学成绩,用一维数组定义如下:int grade30;其元素分别为:grade0

4、,grade29共30个。课件制作:刘达明课件制作:刘达明 023-66834110一维数组的定义说明一维数组的定义说明第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)4/113 数组名数组名定名规则和变量名相同,遵循标识符标识符定名规则。它表示各数组元素的统一名字,用以唯一标识数组。数组名后是用方括号方括号的常量表达式常量表达式,不能用圆括号代替。如int a(20);是错误的。常量表达式的值表示数组中所包含的元素的个数,即数组的长度。如int a20;表示数组a有20个元素,分别为a0、a1、a19。注意不能使用数组元素a20。常量表达式中可以包括常量常量和符号常量

5、符号常量,不能包含变量。即在C语言中不允许对数组进行动态定义,数组的大小不会随着程序运行中的变化而改变。错误定义:int n;scanf(“%d”,&n);float bn;。正确定义:#define N 30 float bN;int i10;。类型说明符表示数组元素具有的数据类型,可以是int、short、long、char、unsigned、float、double等。相同类型的数组可以在同一个类型说明符下一起说明,互相间用“,”隔开。如:int a4,b10,c20;。注意:注意:数组必须先定义,后使用。课件制作:刘达明课件制作:刘达明 023-668341102 2、一维数组的引用、

6、一维数组的引用第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)5/113 数组的具体使用对象是其中的数组元素。在一个数组定义好后,在内存中分配一组连续的存储空间。如:int a5;存储方式见右图。数组元素的引用格式为:数组名数组名 下标下标;这里的下标与数组定义时不同,不仅可以是整型常量或整型表达式,还可以是含有已赋值变量的整型表达式。数组的下标从0开始算起。如:b0=b5+b7-b2*3。又如:int i15;int n=3;i0=-10;i5=6;in*4=9;a0=1内存用户数据区内存用户数据区a1=3a2=2592000200220042008a3=-1a4=-

7、10200600000001000000001111011011111111000000110000000000000011000000011111111111111111课件制作:刘达明课件制作:刘达明 023-66834110一维数组的引用说明一维数组的引用说明第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)6/113 数组元素和普通基本型变量一样的使用,可出现在C语言表达式中的任何地方。C语言规定只能逐个引用数组元素,而不能一次引用整个数组。C语言不提供数组下标越界的保护,设计时要注意。如:int b5;只能有效引用b0、b1、b2、b3、b4。如果程序中出现b5

8、,这时C的编译系统不会出错,但b5的值是 不确定的。课件制作:刘达明课件制作:刘达明 023-668341103 3、一维数组的初始化、一维数组的初始化第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)7/113a0=1内存用户数据区内存用户数据区a1=3a2=2592000200220042008a3=-1a4=-10200600000001000000001111011011111111000000110000000000000011000000011111111111111111 数组在定义后,它所占有的存储单元中的值是不确定的,引用数组元素之前,必须保证数组的元素

9、已经被赋以确定的值。对数组元素的初始化可以用以下方法实现:通过赋值语句或输入语句对数组中的元素赋值。在数组定义时对数组中的元素赋值。对数组元素赋值的方法是从数组的第一个元素开始依次给出初始表,表中各值之间用逗号分开。一般格式为:static static =如:int a5=1,3,259,-1,-10;static int b5=1,3,259,-1,-10;char word5=a,b,c,d,e;课件制作:刘达明课件制作:刘达明 023-66834110一维数组的初始化说明:一维数组的初始化说明:第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)8/113 是用逗号

10、分隔的数据。若对数组中的所有元素都赋初值,可不必指出元素个数,即可以不指定数组长度。如:int a=1,3,259,-1,-10;也表示数组a有5个元素。它等价于:int a5=1,3,259,-1,-10;也等价于 a0=1;a1=3;a2=259;a3=-1;a4=-10。而没有给出数组长度的赋初值,即使后面每个元素的初值全是0,也要写出来。如:int b=1,2,3,0,0,0;认为是6个元素的数组,它等价于:int b6=1,2,3;。中数据的类型必须与所指定的数据类型一致。在C语言中,数组元素的下标值依次为0、1、2、,在n个元素组成的一维数组中,最后一个元素的下标为n-1。课件制作

11、:刘达明课件制作:刘达明 023-66834110一维数组的初始化说明(续):一维数组的初始化说明(续):第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)9/113 C语言规定对数组进行置初值时,如果是静态存储(static为关键字)数组和外部存储(extern)数组。在数组不赋初值时,系统会对所有数组元素自动赋以0值或0值。如:static int a3;等价于 static int a3=0,0,0;。如果只定义int a5;而不赋初值时,则各元素的值是不确定的。对数组的全部元素都赋0为初值,可以写成:int a5=0,0,0,0,0;而不能写成:int a5=0*

12、5;。可以只给数组中的前面一部分元素赋初值,后面没有赋初值的元素系统自动赋以0值或0值。如:int a5=1,2,3;等价于:int a5=1,2,3,0,0;也等价于:int a=1,2,3,0,0;。课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)10/113 1 1、指向基本数据类型变量的指针变量、指向基本数据类型变量的指针变量二、二、指向指向一维数组的指针变量一维数组的指针变量3i变量名变量名变量值变量值存储单元存储单元变量变量i=3内存用户数据区内存用户数据区2000变量变量j=6变量变量k=9变量变量

13、i_pointer200020022004301000001001000000000000001100000000000001100000000020002000i_pointeri30103间接访问:间接访问:2000i3直接访问:直接访问:int i,j,k,*i_pointer=&i;i=3;j=6;k=9;执行执行i_pointer+后,后,i_pointer已不再指向已不再指向i了,了,而是指向了下一个而是指向了下一个j,但在这里这样用无意义。,但在这里这样用无意义。int i;给变量i分配2个字节的存储单元i=3;在i的存储单元中的值为3。课件制作:刘达明课件制作:刘达明 023-

14、66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)11/113200032000i_pointeri3010*i_pointer&b&bp2b*p2&a&ap1a*p1指向基本数据类型变量的指针变量指向基本数据类型变量的指针变量(续续1)1)int i,*i_pointer;i_pointer=&i;若:i=3;则:*i_pointer也为3。float a,*p1;p1=&a;char b,*p2;p2=&b;指针与指针变量通过指针与指针变量通过&建立联系:建立联系:int i,*pi,*pi1;pi=&i;/*指针变量pi已指向变量i*/pi1=pi;

15、这时*pi和*pi1都相当于变量i。即:*pi=3;或*pi1=3;等价于 i=3;char c,*pc;pc=&c;/*指针变量pc已指向变量c*/这时*pc相当于变量c。即:*pc=3;等价于 c=3;float f,*pf;pf=&f;/*指针变量pf已指向变量f*/这时*pf相当于变量f。即:*pf=3.6;等价于 f=3.6;错误赋值:错误赋值:pf=1000;但pf=NULL除外。间接运算符间接运算符*与取地址运算符与取地址运算符&同级,同级,且右结合且右结合。如:*&i=3;等价于 i=3;或*(&i)=3;又:int a,*p=&a;则:&*p等价于&(*p)或&a都表示变量a

16、的地址。而*&a则与*p等价,都表示变量a的内容。课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)12/113指针变量的运算:指针变量的运算:指针变量是一个变量,因此可以进行某些运算。但指针的本质是一个地址,其运算具有一些特别的性质,不能用普通变量的规则运算来作为指针运算的方式。指针指针变量加变量加(减减)一个整数的一个整数的算术运算算术运算:只有:加、减(+、-、+、-)运算。+、+代表指针前移,-、-代表指针后移。指针变量每加(或减)1,就指向它指定的数据类型的下一个(或上一个)元素的位置。C C语言规定语言

17、规定,一个指针变量加(减)一个整数并不是简单地将指针变量的原值加(减)一个整数,而是将该指针变量的原值(是一个地址)和它指向的变量所占用的内存单元字节数相加(减)。如:p+i(p是指针变量,i是整数),代表的地址计算:p+c*i(c为指针变量所指向的数据类型所占内存的字节数)。运算:p+、p-,+p,p-=i,p+=i,p=p+i,p=p-i等(这里i表示整型数据)。这些运算的结果仍为指针结果仍为指针。如:int a,b,c,d,*p;p=&b;当执行p+;(或p=p+1;)时,p就指向变量c,相当于p=&c;而执行p-时,p就指向变量a,相当于p=&a。又如:float e,f,x,y,z,

18、*p2;p2=&x;当执行p2=p2+2;(或p+=2;)时,p2就指向变量z,相当于p=&z;而执行p2=p2-2;(或p-=2;)时,p2就指向变量e,相当于p=&e。两个指针变量之间的两个指针变量之间的算术算术运算运算:只有减法(-)运算。只有指向同一数组的两个指针变量之间才能进行这种运算,否则两个指针变量之间的运算毫无意义(但在程序中不会报错)。指向同一数组的两个指针变量之差,是两个指针之间的元素个数。结果为个数结果为个数。指向基本数据类型变量的指针变量指向基本数据类型变量的指针变量(续续2)2)课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(

19、第四章(第四章 指针与数组)指针与数组)13/113如:p1=&a1;p2=&a4;则p2-p1=4-1=3,表示p1与p2之间有3个数组元素。而p1-p2=-3。注意:注意:两个指针变量进行加法运算,如p1+p2,并无实际意义,并且是非法的指针运算。两个指针变量之间的两个指针变量之间的比较比较(关系关系运算运算):两个指针之间关系运算是比较两个指针所指向的地址关系,其运算符有:=、!=、=。比较运算结果为:真真(1)(1)或假或假(0)(0)。如:p1=&a1;p2=&a4;则:p1=p2为假(0),p1!=p2为真(1),p1p2为假。p1=p2;p1=p2;表示p1、p2指向同一数组元素

20、地址。p1p2;p1p2;表示p1比p2的地址值大,处于高地址位置。p1p2;p1p2;表示p1比p2的地址值小,处于低地址位置。注意:注意:只有两个指针指向同一数组的元素时,进行比较才有意义,这时指向前面的元素的指针变量“小于”指向后面的元素的指针变量。特别注意:如果两个指针变量不是指向同一数组,则这两个指针变量进行比较毫无意义(但在程序中不会报错)。指针标量可以指向一个空值:指针标量可以指向一个空值:即该指针变量不指向任何变量。在stdio.h文件中有如下定义:#define NULL 0,当定义int*p=NULL;时,相当于int*p;p=NULL;或p=0;表示p不指向任何变量,而是

21、指向地址为0的单元,表明p是空指针。也就是说,有效数据的指针不指向0单元。注意:注意:空指针与未对p赋值是两个不同概念。空指针p是对p赋0值,而未对p赋值并不等于p无值,只是它是一个无法预料的值,这就可能影响有用单元。因此在引用指针变量之前,一定要对它赋值。任何指针变量或地址都可以与NULL作相等或不相等的比较。如:p=NULL,如果结果为真(1),表明p为空指针,否则p不是空指针。指向基本数据类型变量的指针变量指向基本数据类型变量的指针变量(续续3)3)课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)14/11

22、3 数组是同一类型变量组成的有序集合,其本身存储的是各种类型的数据;而指针是专门用来存放其它变量的地址,当一个指针变量指向某一数组时,在对该数组元素的存取方式上,通过数组的下标与通过数组指针的运算访问数组元素是十分相似的。一个变量可以有一个地址相对应,而一个数组包含若干个元素。每个数组元素都在内存中占用存储单元,同样有一个地址相对应。指针变量可以指向变量,所以也可以指向数组和数组元素,即把数组起始地址或某一元素的地址放到一个指针变量中。所谓数组的指针数组的指针是指数组的起始地址,而数组元素的指针数组元素的指针是指数组元素的地址。实际上,定义的数组名就是一个指针数组名就是一个指针,表示数组的首地

23、址,是一个固定值,一个常量,与定义的指针变量是不同的。对数组的访问,即对数组元素的操作,可使用:下标法下标法,即直接使用数组的下标方式,如:a0、a4等;和指针法指针法,即通过指向数组元素的指针找到所需的数组元素。指向数组元素的指针指向数组元素的指针 定义:int a10,*p;数组元素相当于一个变量,因此每个元素的地址都可以赋给对应类型的指针变量。如:p=&a0;、p=&a2;、p=&a9;等都是合法的。p=&a8;表示指针变量p指向了数组的第9个元素,而p=&a0;则表示指针变量p指向了数组的第1个元素。这时指针变量p与数组a就建立了关系,我们可以通过指针变量p访问数组a了。注意:注意:数

24、组的类型与指针变量的类型应一致。2 2、指向一维数组的指针、指向一维数组的指针课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)15/113 C语言规定数组名代表数组的首地址,即第0号元素的地址。因此:当定义int a10,*p;时,赋值语句:p=&a0;与p=a;是等价的。这时指针变量p就指向了数组a。注意:注意:数组a不代表整个数组元素,“p=a;”的作用是“把数组a的首地址赋给指针变量p”,而不是“把数组a各元素的值赋给p”。但是,这时就把数组a与指针变量p建立起了一种关系,我们可以通过指针变量p访问数组a了

25、。如下定义与赋值:int a10;int*p;p=a;与:int a10;int*p;p=&a0;是等价的。与:int a10;int*p=a;也是等价的。与:int a10;int*p=&a0;也是等价的。“int*p=a;”的作用是将数组a的首地址(即a0的地址)赋给指针变量p,而不是赋给*p。指向数组的指针指向数组的指针内存用户数据区内存用户数据区a0=1a1=3a2=2592000200220042008a3=-1a4=-10200600000001000000001111011011111111000000110000000000000011000000011111111111111

26、11120043010pp=&a2;p=&a0;或或p=a;p课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)16/113有如下定义:int a20,*p;如果p的初值赋值为:p=a;或p=&a0;则有:p或a均表示数组a的首地址,即&a0。这时的*p=2;或*a=2;都表示对a0元素赋值为2,即相当于:a0=2;。p+i或a+i就是ai的地址,即&ai。因此*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素ai,这时*(p+i)=3;或*(a+i)=3;就相当于ai=3;。因此*(p+i),*(a+i

27、),ai是等价的。注意:注意:在C编译时,对数组ai的处理实际上就是处理成*(a+i)的,即按数组首地址加上相对位移量得到要找的元素的地址,然后找出该单元中的内容。因此*(a+i)的表示法比ai的表示法在程序执行时要快得多。由此可知,下标运算符实际上是变址运算符变址运算符,即将ai按a+i计算地址,然后找出此地址单元中的值。通过指针引用数组元素通过指针引用数组元素a数组存储区数组存储区a0a1a22000200220042000+2*iai3010pp,ap+2,a+2p+i,a+ia192038p+19,a+19p+1,a+1课件制作:刘达明课件制作:刘达明 023-66834110第一节第

28、一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)17/113指向数组的指针变量也可以带下标。如:pi与*(p+i)是等价的,也与*(a+i)和ai是等价的。注意:注意:pi是数组元素的值而不是指针。因此*(p+i),*(a+i),ai,pi等价。如果:int a10,*p;p=&a4;则:p2表示a6元素,p-3表示a1元素。引用数组元素的三种方法引用数组元素的三种方法引用数组元素的方法分为两大类:下标法下标法(如:a2)和指针法指针法(又有两种方式:通过数组名计算数组元素地址,找出元素的值,如:*(a+2);和用指针变量指向数组元素,如:*(p+2)。例例 4.1 有一个整型

29、数组,共有一个整型数组,共10个元素,输出数组中的全部元素。个元素,输出数组中的全部元素。(详见教材详见教材P107)下标法:#include main()int a10,i;for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);for(i=0;i10;i+)printf(“%6d”,ai);通过数组名计算元素地址:#include main()int a10,i;for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);for(i=0;i10;i+)printf(“%6d”,*(a+i);通过指针变量操作数组元素:#include

30、main()int a10,i,*p;for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);for(p=a;p(a+10);p+)printf(“%6d”,*p);课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)18/113在例4.1中,所使用的三种方法的比较如下:第1和第2种方法执行效率是相同的,都是将ai转换为*(a+i)处理。这两种方法找数组元素费时较多。第3种方法比第1和第2种方法执行快,用指针变量直接指向元素,不必每次都重新计算地址,像p+这样的自加操作是比较快的,它是有

31、规律地改变地址值的。用下标法比较直观,能直接知道是第几个元素。如a5表示第5号元素(从0开始)。用地址法或指针变量的方法不直观,难以很快地判断出当前处理的是哪个元素。如进行多次p+操作后p值已改变,就要分析当前指针变量p指向哪个元素。但使用指针变量方式在复杂的数据结构中就显示出它的灵活性。使用指针变量对数组操作时应注意的问题使用指针变量对数组操作时应注意的问题 指针变量可以实现使本身的值改变,而数组名是表示一个固定不变的数组首地址。如:int a10,*p=a;则,执行p+(或p+=1或p=p+1)后,p就指向下一个元素a1。当定义int a10,*p;p=&a6;执行-p(或p-=1或p=p

32、-1)后,p就指向上一个元素a5。但是:for(p=a;a(p+10);a+)printf(“%d”,*a);则是非法的,不能实现a+且无意义。定义int a10,*p;p=&a9;,这时再执行p=p+1;操作,p就指向了数组a以后的内存单元了,而不再指向数组a了。如果引用a10,C系统不作为非法,而是转换为*(a+10)处理,但它已超出数组a的范围了,因此不能得到预期的结果。所以,在使用数组a或指针变量p时,应保证数组在有效范围内引用,保证指针变量是指向数组中有效的元素的。课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指

33、针与数组)19/113特别注意指针变量的当前值。如以下程序:指针变量的运算 p+(p+(或或p+=1p+=1),使p指向下一元素,如果p的初值为数组a的首地址的话,这时p就指向a1元素了。若再执行*p,就取出了a1的值。*p+p+,由于+和*同一优先级,结合方向为自右而左,因此它等价于*(p+)。作用是#include main()int a10,i,*p;p=a;for(i=0;i10;i+)scanf(“%d”,p+);printf(“n”);for(i=0;i10;i+,p+)printf(“%6d”,*p);这是错误的程序。第一个循环中的p+运行完后使它不指向数组a了。#include

34、 main()int a10,i,*p;p=a;for(i=0;i10;i+)scanf(“%d”,p+);printf(“n”);p=a;for(i=0;ia1,则交换;然 后比较第二个数与第三个数;依次类推,直至第n-1个数和第 n个数比较为止第一趟冒泡排序,结果最大的数被安置在 最后一个元素位置上(2)对前n-1个数进行第二趟冒泡排序,结果使次大的数被安置在 第n-1个元素位置(3)重复上述过程,共经过n-1趟冒泡排序后,排序结束 注:在第一趟比较中要进行N1次两两比较,在第J趟比较中要进行NJ次比较。p=a;while(pa+100)printf(“%6d”,*p+);p=a;whil

35、e(pai+1真假a i ai+1输入n个数给a1到an输出a1到an课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)23/113例例4.2(4.2(续续2)2)#include main()int a11,i,j,t;printf(Input 10 numbers:n);for(i=1;i11;i+)scanf(%d,&ai);printf(n);for(j=1;j=9;j+)for(i=1;iai+1)t=ai;ai=ai+1;ai+1=t;printf(The sorted numbers:n);for(i

36、=1;i11;i+)printf(%d,ai);#include main()int a11,i,j,t,*p;printf(Input 10 numbers:n);p=a+1;for(i=1;i11;i+)scanf(%d,p+);printf(n);for(j=1;j=9;j+)for(i=1;iai+1)t=ai;ai=ai+1;ai+1=t;printf(The sorted numbers:n);p=a+1;for(i=1;i11;i+,p+)printf(%d,*p);或课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与

37、数组)指针与数组)24/113例例4.2(4.2(续续3)3)以输入6个整数为例说明其执行过程:第一次循环示意图(共6个数,循环5次):第一次第二次第三次第四次第五次结果最大课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)25/113例例4.2(4.2(续续4)4)第三次第四次结果 第二次循环示意图如下(共5个数,循环4次):85420第一次第二次次大课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)26/113例例4.2(4.2(续

38、续5)5)024589 结果20第一次02结果 第五次循环4520 第二次4250第三次4205结果 第三次循环示意图如下:4520 第一次240第二次204结果240第一次 第四次循环示意图如下:课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)27/113例例4.34.3 求斐波那契Fibonacci数列:1,1,2,3,5,8,的前40项。解:在第三章中讲过(详见教材P77的例3.31),这里使用数组实现。#include main()int i,f40=1,1;for(i=2;i40;i+)fi=fi-2+

39、fi-1;for(i=0;i40;i+)if(i%4=0)printf(n);printf(%12d,fi);f0=1,f1=1for i=0 to 39输出:fifor i=2 to 39fi=fi-1+fi-2)3(2 1)2(12)1(1 1 nnFnFnFnFnF课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)28/113例例4.44.4 用选择法对10个数排序。输入n 个数给a1 到 anfor i=1 to n-1for j=i+1 to najak真假k=j输出a1 到 ank=iaiaki!=k真

40、假排序过程排序过程:(1)首先通过n-1次比较,从n个数中找出最小的数的下下标标,通过下标找到对应的元素并与第一个数交换第一趟选择排序,结果最小的数被安置在第一个元素位置上。(2)再通过n-2次比较,从剩余的n-1个数中找出关键字次小的记录,将它与第二个数交换第二趟选择排序。(3)重复上述过程,共经过n-1趟排序后,排序结束。课件制作:刘达明课件制作:刘达明 023-6683411029/113例例4.44.4(过程)(过程)例初始:49 38 65 97 76 13 27 kji=11349一趟:13 38 65 97 76 49 27 i=22738二趟:13 27 65 97 76 49

41、 38 三趟:13 27 38 97 76 49 65 四趟:13 27 38 49 76 97 65 五趟:13 27 38 49 65 97 76 六趟:13 27 38 49 65 76 97 kkkkjjjjjjjjjj课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)30/113例例4.44.4(程序)(程序)#include main()int a11,i,j,k,x;printf(Input 10 numbers:n);for(i=1;i11;i+)scanf(%d,&ai);printf(n);fo

42、r(i=1;i10;i+)k=i;for(j=i+1;j=10;j+)if(ajak)k=j;if(i!=k)x=ai;ai=ak;ak=x;printf(The sorted numbers:n);for(i=1;i11;i+)printf(%d,ai);课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)31/113例例4.54.5 用折半法查找一个数。有15个数按由大到小的顺序存放在一个数组中,输入一个数,要求用折半法找出该数在数组中第几个元素的值位置。如果该数不在数组中,则打印出“无此数”。对于无序的一组数据

43、,只能使用顺序查找法顺序查找法查询数据。折半查找折半查找(也称对分查找)的前提是已经排好序。折半查找法的思想折半查找法的思想:使用均分确定的方法,先测区间的中点元素;如果被查找信息的关键字小于中点元素,则关键字在测中点的前半部分(降序时为后半部分);如果被查找信息的关键字大于中点元素,则关键字在测中点的后半部分(降序时为前半部分)。继续该过程直到找到该关键字或无法二分为止。课件制作:刘达明课件制作:刘达明 023-66834110第一节第一节 一维数组一维数组(第四章(第四章 指针与数组)指针与数组)32/113例例4.54.5 程序。#include#define N 15main()int

44、 bins(int a,int n,int x);int aN,i=1,x;scanf(“%d”,&a0);while(i=ai-1)i+;scanf(“%d”,&x);pos=bins(a,N,x);if(pos!=-1)printf(“%d,%d”,pos,x);else printf(“Not found”);/*升序的折半法查找*/int bins(int a,int n,intx)int low,high,mid;low=0;high=n-1;while(lowamid)low=mid+1;else if(x1课件制作:刘达明课件制作:刘达明 023-66834110二维数组可看成若

45、干元素的一维数组二维数组可看成若干元素的一维数组第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)39/113 在C语言中,二维数组采用类似于float a34;的定义,使我们可以把二维数组看成是一种特殊的一维数组:它的元素又是一个一维数组。如:float a34;把a看成是一维数组,它有3个元素:a0、a1、a2,每个元素又包括4个元素的一维数组。而a0、a1、a2就看成是包含4个元素的一维数组的数组名。即定义:float a34;相当于定义:float a04,a14,a24;。a0 =a00 a01 a02 a03 a1 =a10 a11 a12 a13 a2 =a

46、20 a21 a22 a23 a34 a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 课件制作:刘达明课件制作:刘达明 023-668341105 5、二维数组的初始化、二维数组的初始化第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)40/113 二维数组与一维数组一样,可以对二维数组的元素进行赋值或者初始化。数组在定义后,它所占有的存储单元中的值是不确定的,引用数组元素之前,必须保证数组的元素已经被赋以确定的值。二维数组初始化的方法如下:分行给二维数组赋初值分行给二维数组赋初值。int a23=1,2,3,5,6,7;第

47、一个内花括号的值赋给数组的第一行,第二个内花括号的值赋给数组的第二行。所有数据写在一个花括弧内所有数据写在一个花括弧内,按顺序赋初值,按顺序赋初值。int a23=2,3,5,6,7,8;它将第一组3个数赋给数组的第一行,第二组3个数赋给数组的第二行。该方法相对简单,但是,当数组元素较多时,容易出现混乱、遗漏、出错。在行、列数较多时,使用第一种方法较好。对于定义的静态存储(关键字为static)数组,如果没有赋初值,则系统自动将全部元素赋以0值或0值。如:static int a22;相当于static int a22=0,0,0,0 而对定义的int a22;如果不对其赋初值,则数组中各元素

48、的值是不确定的。课件制作:刘达明课件制作:刘达明 023-66834110对部分元素赋初值对部分元素赋初值第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)41/113 数组在对部分元素赋初值时,如果后面的数组元素不赋初值,系统会对所有数组元素自动赋以0值。如:int a23=0,2,1;相当于:int a23=0,2,0,1,0,0;。再如:static int d23=8,5,9;相当于:static int d23=8,5,0,9,0,0;。又如:int b23=1,0,3;相当于:int b23=1,0,3,0,0,0;。如果对全部元素都赋初值时,则定义数组时,第

49、一维(行)的长度可以不指定,但第二维(列)的长度不能省需要指定。如:int a4=1,2,3,4,5,6,7,8,9,10,11,12等价于:int a34=1,2,3,4,5,6,7,8,9,10,11,12;。课件制作:刘达明课件制作:刘达明 023-66834110键盘输入赋值键盘输入赋值第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)42/113 通过键盘输入二维数组的数组元素,一般需要使用二重循环的形式进行。可以先行输入,也可先列输入。先行输入方式先行输入方式 int a34;for(i=0;i2;i+)for(j=0;j3;j+)scanf(“%d”,&ai

50、j);先列输入方式先列输入方式 int a34;for(j=0;i3;j+)for(i=0;i2;i+)scanf(“%d”,&aij);说明说明:不管是先行输入,还是先列输入,在计算机存储中数组元素仍然是按行存储的。课件制作:刘达明课件制作:刘达明 023-66834110通过赋值语句通过赋值语句赋初值赋初值第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)43/113 如:int a22;a00=1;a01=2;a10=3;a11=4;。在定义数组时也可以只对部分元素赋值,而省略第一维的长度,但应使用分行赋值方式。如:int a4=1,3,1,0,0,9;它与 int

51、 a34=1,3,1,0,0,9;等价。注:注:错误的初始化定义:int a33;a=1,2,3,4,5,6,7,8,9;这是错误的。而int a33;a33=1,2,3,4,5,6,7,8,9;也是错误的赋值方式。课件制作:刘达明课件制作:刘达明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)44/113 C语言允许多维数组。多维数组的定义形式为:类型说明符类型说明符 数组名数组名常量表达式常量表达式1 常量表达式常量表达式2常量表达式常量表达式n;例如:定义三维数组的方法为:int a234;定义四维数组的方法为:float f23410;

52、等。多维数组元素在内存中的存放顺序仍然是“按行优先”,其排列顺序为:第一维的下标变化最慢,最右边的下标变化最快。如:int a234;定义的是一个三维数组,共有2*3*4=24个元素。其中第一维下标变化最慢,第二维下标变化次之,第三维下标变化最快。在内存的存放顺序为:a000,a001,a002,a003,a010,a011,a012,a013,a020,a021,a022,a023,a100,a101,a102,a103,a110,a111,a112,a113,a120,a121,a122,a123。二、二、多多维数组的概念维数组的概念课件制作:刘达明课件制作:刘达明 023-6683411

53、0第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)45/113 分行初始化分行初始化:int a234=1,2,3,4,5,6,7,8,0,0,0,0,13,14,15,16,17,18,19,20,21,22,23,24。顺序赋值初始化顺序赋值初始化:int a234=1,2,3,4,5,6,7,8,0,0,0,0,13,14,15,16,17,18,19,20,21,22,23,24;。也可省略第一维的长度初始化也可省略第一维的长度初始化:int 34=1,2,3,4,5,6,7,8,0,0,0,0,13,14,15,16,17,18,19,20,21,22,23,

54、24;。可将它看成2个二维数组a034和a134。也可看成是6个特殊的一维数组:a004、a014、a024、a104、a114、a124。多多维数组的初始化维数组的初始化课件制作:刘达明课件制作:刘达明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)46/113 1 1、二维数组的地址、二维数组的地址 关于一维数组与指针关系的结论可以推广到二维数组、三维数组等多维数组。可以把二维数组看成是这样的一维数组:它的每个单元本身又是一个一维数组。例如:int a43=1,3,5,7,9,11,13,15,17,19,21,23;这里a是一个数组名。数

55、组a包含4个元素(即4行):a0,a1,a2,a3,而每个元素又是一个包含3个元素(即3列元素)的一维数组。如a1代表的一维数组包括:a10,a11,a12三个元素。三、三、指向二维数组的指针变量指向二维数组的指针变量=a00 a01 a02 =a10 a11 a12 =a20 a21 a22=a30 a31 a32 a0a1a2aa3=1 3 5 =7 9 11 =13 15 17=19 21 23 a0a1a2aa3a0a1a2aa31000100610121018a00 a01 a02a10 a11 a12a20 a21 a22a30 a31 a32a+1a+2a+3课件制作:刘达明课件

56、制作:刘达明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)47/113 从二维数组的角度来看,a a代表代表整个整个二维数组的首地址二维数组的首地址,也就是二维数组a的第0行的首地址。假设二维数组a的首地址为:1000,那么,a的地址应为1000。则a+1为1006,因为第0行有3个整型数据,因此a+1a+1的含义是a1a1的地址的地址。a+2a+2代表第2行的首地址,它的值是1012,是a2a2的地址的地址。a+3a+3代表第3行的首地址,它的值是1018,是a3a3的地址的地址。既然把a0、a1、a2、a3看成是4个一维数组名,而C语言又

57、规定了数组名代表数组的首地址。因此a0a0代表了第0行一维数组中第0列元素的地址,即&a00&a00。同样a1a1代表了第1行一维数组中第0列元素的地址,即&a10&a10。a2a2代表了第2行一维数组中第0列元素的地址,即&a20&a20。a3a3的值是&a30&a30。作为一维数组a0的其他元素的地址可以使用a0+0、a0+1、a0+2分别表示元素a00、a01、a02的地址。一般地,ai+jai+j即表示第i行第j列元素的地址,即&aij&aij。如a1的值是1006,则a1+1表示1008,它是&a11的值。有关二维数组地址的描述:有关二维数组地址的描述:课件制作:刘达明课件制作:刘达

58、明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)48/113 由于a+1表示a1的地址,因此*(a+1)就是a1的值。a表示a0的地址,因此*a也就是a0的值。一般地,a+i表示ai的地址,因此*(a+i)就是ai的值。所以*a a与a0a0是等价的,a1a1与*(a+1)(a+1)是等价的。一般地,aiai与*(a+i)(a+i)是等价的。而a0又表示a00的地址,a1又表示a10的地址,ai又表示ai0的地址,因此*(a+1)(a+1)、*a a、*(a+i)(a+i)虽然形式上是指针运算符,似乎指的是变量地址中所存储的值,但它仍然是地址

59、仍然是地址,它们分别是a1、a0、ai的值。而a1、a0、ai仍然是地址,它们分别是a10、a00、ai0的地址。注意:注意:a+i并不是一个变量,它是ai的地址。a是二维数组名,代表数组首地址,不能用*a来得到a00的值。*a相当于*(a+0)即表示a0,它是第0行地址。a是行指针,*a是列指针。*a表示a00的值。同样*(a+1)是a10的值。有关二维数组地址的描述有关二维数组地址的描述(续续1)1):课件制作:刘达明课件制作:刘达明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)49/113 二维数组元素的值的表示二维数组元素的值的表示

60、既然a1与*(a+1)是等价的,那么a1+2就可以写成*(a+1)+2,而a1+2是a12的地址。因此*(a1+2)就是a12的值,所以*(*(a+1)+2)也代表a12的值。(注意值与地址的表示与差别注意值与地址的表示与差别)。即a12a12、*(a1+2)(a1+2)、*(*(a+1)+2)(a+1)+2)三个是等价的,都表示数组元素a12的值。同样a01a01、*(a0+1)(a0+1)、*(*a+1)a+1)三个是等价的,都表示数组元素a01的值。一般地,aijaij、*(ai+j)(ai+j)、*(*(a+i)+j)(a+i)+j)都表示aijaij的值,甚至还可以写成(*(a+i)

61、j(a+i)j的形式。有关二维数组地址的描述有关二维数组地址的描述(续续2)2):课件制作:刘达明课件制作:刘达明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)50/113 ai从形式上看是数组a中的第i个元素。如果a是一维数组名,则ai代表数组a第i个元素所占的内存单元的值,ai是有物理地址的,是占内存单元的。但如果a是二维数组名,则ai代表一维数组名,它本身并不占实际的内存单元,也不存放数组a中各个元素的值,它只是一个地址。以下是几种表示形式的对比:有关二维数组地址的描述有关二维数组地址的描述(续续3)3):表示形式表示形式 含义含义 地

62、址值地址值&a 指向二维数组的指针 1000a 二维数组名,指向一维数组a0,即第0行首地址 1000a0,*(a+0),*a 第0行第0列元素地址 1000a+1,&a1 第1行首地址 1006a1,*(a+1)第1行第0列元素地址 1006a1+2,*(a+1)+2,&a12 第1行第2列元素地址 1010*(a1+2),*(*(a+1)+2),a12 第1行第2列元素的值 元素值为11课件制作:刘达明课件制作:刘达明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)51/113 二维数组名二维数组名(如如a)a)是指向行的是指向行的,因此a

63、+1中的1代表一行中全部元素所占的字节数。一维数组名一维数组名(如如a0,a1)a0,a1)是指向列元素的是指向列元素的,a0+1中的1代表一个元素所占的字节数。在行指针面前加一个在行指针面前加一个*就转换为列指针就转换为列指针,如a和a+1是行指针,而*a和*(a+1)就成了列指针,分别指向数组a的第0行第0列的元素和第1有关二维数组地址的描述有关二维数组地址的描述(续续4)4):1000 1002 1004 1 3 51006 1008 1010 7 9 111012 1014 1016 13 15 171018 1020 1022 19 21 23aa+1a+2a+3a0a0+1a0+2

64、行第0列的元素。反之,在列指在列指针前面加针前面加&就成为行指针就成为行指针,如a0是指向第0行第0列的元素的列指针,而&a0它就指向二维数组的第0行(由于a0与*(a+0)等价,因此&a0与&*a等价)。课件制作:刘达明课件制作:刘达明 023-66834110第二节第二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)52/113 不要把&ai简单的理解为ai的物理地址,因为并不存在ai这个变量。它只是一种地址的计算方法,能得到第i行的地址,&ai和ai的值是一样的,但它的含义却不同。&ai&ai或或a+ia+i指向行指向行,而aiai或或*(a+i)(a+i)指向列指向列。当

65、下标j=0时,&ai和ai+j的值相等。*(a+i)只是ai的另一种表示形式。在二维数组中,a+i=ai=*(a+i)=&ai=&ai0即它们的地址值是相等的。2 2、指向数组元素的指针变量、指向数组元素的指针变量 对于二维数组元素的操作,可像一维数组用指针变量对它的操作一样。但在操作中要注意数组元素的行和列的问题。二维数组元素在存储中,是按行存储的。如果一个指针变量指向某个存储单元,指针的移动,也是顺序的指向相应存储单元。有关二维数组地址的描述有关二维数组地址的描述(续续5)5):课件制作:刘达明课件制作:刘达明 023-66834110例例4.64.6 用指针变量输出数组元素的值。第二节第

66、二节 二维数组二维数组(第四章(第四章 指针与数组)指针与数组)53/113(详见教材P114的例4.6。)从例子中可以看出,p是一个指向整型变量的指针变量,它可以指向一般的整型变量,也可以指向整型的数组元素。每次使p加1,以移向下一元素。如果定义int a43,*p;p=a0;,则aij的值用指针变量p来表示为:*(p+i*3+j),如求a12应为*(p+5)。这里i*n+j(当数组有n列时),就是aij的序号的序号,可用*(p+i*n+j)来表示aij的值。例例4.74.7 用指针变量输出数组元素的值。main()int a34=1,3,5,7,9,11,13,17,19,21,23;int*p;for(p=a0;pa0+12;p+)if(p-a0)%4=0)printf(“n”);printf(“%4d”,*p);运行结果为:1 3 5 7 9 11 13 1517 19 21 23a00 1 0a01 3 1a02 5 2a03 7 3pa23 23 11p+1p+11课件制作:刘达明课件制作:刘达明 023-668341103 3、指向由、指向由m m个元素构成的一维数组的指

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!