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

下载本文档

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

文档简介

哈尔滨工业大学计算机学院,2003年8月,C语言程序设计,傅忠传,第五章数组和指针,本章的学习难点,1.数组的概念及其使用。,3.指针的概念以及数组与指针之间的关系。,2.字符数组以及字符串处理函数在字符串处理操作中的应用。,本章目录,数组指针指针和数组间的联系指针数组*指向指针的指针*带参数的main函数和命令行参数*动态数组的实现*关于面向过程的程序设计*关于防御性程序设计*关于程序质量的重要性,数组,数组类型的应用场合定义、初始化和引用一维数组应用举例一维数组名作函数参数二维数组及二维数组作函数参数应用举例字符数组6.1.字符数组与字符串的关系6.2.字符数组的输入输出6.3.字符串处理函数*6.4.字符数组应用举例1、2,数组类型的应用场合,排序算法与数组两个数由小到大排序:三个数由小到大排序:十个数由小到大排序:一百个数由小到大排序:,数组,数组的概念,数组,由若干个相同类型的相关数据项按顺序存储在一起,构成数组(array);数组实际上是同种类型、有序的数据的集合。,数组名,如果用一个统一的名字标识这组数据,那么这个名字就称为数组名。,数组元素,构成数组的每一个数据项称为数组的元素(element)。,说明,同一数组中的元素必须具有相同的数据类型,而且这组数据在内存中将占据一段连续的存储单元。,数组定义的通用格式,格式,类型数组名下标1下标2下标n;,其中:类型为数组元素的基类型,即每个元素的类型。下标值n表示为所在维的数组元素个数,该维的数组下标的上界是n-1;C语言中数组下标下界始终为。维数是下标的个数。,数组分类,一维数组,二维数组与多维数组,一维数组的定义一维数组的初始化一维数组的引用,二维数组的定义二维数组的初始化二维数组的引用,定义、初始化、引用,一维数组的定义,格式,类型数组名常数表达式;,举例,inta10;/各元素都为整形。定义一个包括10个整形元素的一维数组。元素为:a0、a1、a2a9,注明,数组名定名规则和变量名相同,遵循标识符定名规则。,数组名后使用方括号括起来的常数表达式,不能用圆括号。inta(10);,常数表达式表示元素的个数,即数组长度,而不是数组的上界。上例不能使用a10越界错误!,常数表达式中可以包括常量和符号常量,不能包括变量。如变长数组:设n为整形。动态数据结构scanf(%d,数组必须先定义,然后使用。,一维数组元素在内存中的排列顺序是线性排列即连续存储的。,一维数组元素的引用,使用说明,C规定只能逐个引用数组元素,而不能一次引用整个数组。,引用形式,数组名下标,其中:下标可为整形常量或整形表达式。,举例,a0=a5+an+3-a2*3,使用循环语句完成数组的赋值与输出。main()inti,a10;for(i=0;i=0;i-)printf(%3d,ai);,注明,在数组的引用中,其下标值必须要落在0与n-1之间越界错误!下标越界也不自动监测。,一个数组元素实质上就是一个变量名,数组元素和变量一样使用。,数组元素下标的括号必须是方括号。,一维数组的初始化,在定义数组时,对数组元素赋初值。inta10=0,1,2,3,4,5,6,7,8,9a0=0;a1=1;a2=2;a9=9,可以只给一部分元素赋初值。inta10=0,1,2,3,4a0=0;a1=1;a2=2;a3=3;a4=4初值只赋前5个元素。,如想使一个数组全部为值n,可为:inta10=0,0,0,0,0,0,0,0,0,0与fortran语言不同,不能为:inta10=0*10,在对全部数组元素赋初值时,可以不指定数组长度,例如:inta5=1,2,3,4,5可以写成:inta=1,2,3,4,5,当数组被说明为静态(static)存储类型或外部存储类型(即在所有函数外部定义)时,则在不显式给出初值的情况下,数组元素将在程序编译阶段自动初始化为0。staticinta4等价于staticinta4=0,0,0,0,二维数组的定义,格式,类型数组名常数表达式1常数表达式2;,举例,inta34;,可看成3行*4列矩阵:,inta04inta14inta24;每行都是一个包含4个元素的一维数组。,二维数组的排列顺序,元素为:a00a01a02a03a10a11a12a13a20a21a22a23,按行存储,多维数组,格式,类型数组名常数1常数2常数m;,举例,inta224;,存储顺序,a000a001a002a003a010a011a012a013a100a101a102a103a110a111a112a113,按行存储,二维数组元素的引用,引用形式,数组名下标1下标2,其中:下标可为整形常量或整形表达式。,举例,a23=a12+b7/2,注明,在数组的引用中,其下标值必须要落在该维的上下界之内。,一个数组元素实质上就是一个变量名,数组元素和变量一样使用。,在数组inta34中,a34=5因为3和4已超出上界。,在数组inta34中,a21不能写成a2,1只能写成a21。,二维数组的初始化,分行给二维数组赋初值。inta34=1,2,3,4,5,6,7,8,9,10,11,12;也可将所有数据写在一个花括号内,按数组存储顺序对各元素赋值。inta34=1,2,3,4,5,6,7,8,9,10,11,12,如果对全部元素赋初值(即提供全部初始数据),则定义数据时对第一维长度可以不指定,但第二维长度不能省。inta34=1,2,3,4,5,6,7,8,9,10,11,12;等价于inta4=1,2,3,4,5,6,7,8,9,10,11,12;,一维数组应用举例,冒泡法排序Fibonacci级数(作业)*折半查找,Fibonacci级数,用数组来处理求Fibonacci的前20项。例如:1,1,2,3,5,8,13,21,34,65,,#includemain()inti;staticintf20=1,1;for(i=2;i20;+i)fi=fi-1+fi-2;for(i=0;i20;+i)if(i%5=0)printf(n);printf(%12d,fi);,冒泡法排序,用冒泡法对10个数排序(由小到大)。,482759,248579,245879,245789,245789,245789,482759,482759,482579,482579,428579,冒泡程序,t=aj;aj=aj-1;aj-1=t,注:可以使用a0,折半查找,1,5,6,9,11,17,25,34,38,41,下界low,上界up,中值mid,共有10个已排好序的数据:查找9。,折半查找程序,#includemain()intup=9,low=0,mid,found=0,find;inta10=1,5,6,9,11,17,25,34,38,41;scanf(%d,一维数组名作函数参数,使用简单变量作函数参数,能由实参向形参传递一个数据。使用数组名作函数参数,属于“地址调用”能由主调函数向被调函数传递数组的首地址,并能由被调函数向主调函数传递多个数据。,数组名作为函数参数,传递方式,属于赋地址调用,将实参数组首地址传给虚参,虚参也是一数组名。,虚参要求,必须是数组名。,实参要求,可为另一数组名。,哑实结合,哑实数组具有相同的首地址,即哑实数组第一个元素占用同一存储单元,以后各元素按顺序一一结合。,函数传值(数组名)示意图,地址值,主调函数,实参,地址值,被调函数,实参,实参,形参,调用时,地址值,地址值,形参,形参,执行调用函数,地址值,地址值,从被调用函数返回,修改,已改变,数组名作参数的说明,用数组名作函数参数时,应该在主调函数和被调函数分别定义数组实参数组、形参数组,不能只在一方定义,并且实参数组与形参数组类型必须一致。,2.在被调函数中声明的形参数组的大小n,实际上不起任何作用,因为C编译对形参数组的大小不做检查,只将实参首地址传给形参数组。,3.实参数组和形参数组,既可同名,也可不同名,因它们的数组名代表的是数组的首地址,所以经过“由实参向形参的单向值传递”后,它们便指向了内存中的同一段连续的存储单元。,4.若在被调函数中改变形参数组的元素值,则实参数组中的元素值也会随之发生改变。注意这种改变不是形参传给实参造成的(C语言不允许这种反向的值传递),而是由于形参和实参两个数组在内存中因指向同一地址而共享同一段内存造成的。,选择出运行结果,#defineMAX10intaMAX,i;main()printf(n);sub1();sub3(a);sub2();sub3(a);sub2()intaMAX,i,max=5;for(i=0;imax;i+)ai=i;sub1()for(i=0;iMAX;i+)ai=i+i;sub3(inta)inti;for(i=0;iMAX;i+)printf(%d,ai);printf(n);,02468101214161801234,B)01234024681012141618,C)012345678901234,D)024681012141618024681012141618,D)024681012141618024681012141618,aMAX,intaMAX,求平均值1,有一个一维数组score,内放10个学生成绩,求平均成绩。,#includefloataverage(floatarray10);/*声明*/main()floatscore10,aver;inti;printf(input10scores:n);for(i=0;i10;i+)scanf(%f,floataverage(floatarray10)inti;floataver,sum=0;for(i=0;i10;i+)sum=sum+arrayi;aver=sum/10;return(aver);,求平均值1,/*定义*/,二维数组名作函数参数,转置矩阵(作业)*杨辉三角形*魔幻矩阵*读程序、写结果*矩阵行列转换,魔幻矩阵,函数f中的形参a为一个1010的二维数组,n的值为5,一下程序段的运行结果为。,f(inta1010,intn)inti,j,k;j=n/2+1;a1j=1;i=1;for(k=2;kn)i=i+2;j=j-1;elseif(in)j=1;if(aij=0)aij=k;elsei=i+2;j=j-1;aij=k;,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,输出运行结果,写出以下的程序运行结果。,main()inta33=1,3,5,7,9,11,13,15,17;sum=func(a);printf(nsum=%dn,sum);func(inta3)inti,j,sum=0;for(i=0;i3;i+)for(j=0;j3;j+)aij=i+j;if(i=j)sum=sum+aij;return(sum);,Sum=6,矩阵行列转换,将一个二维数组行和列元素互换,存到另一个数组中。,main()inta23,b32,i,j;for(i=0;i=1;i+)for(j=0;j=2;j+)scanf(%d,转置矩阵,求55阶矩阵A的转置矩阵。,#includemain()inta55=1,2,25,i,j,t;for(i=0;i=4;i+)for(j=0;j=i;j+)t=aij;aij=aji;aji=t;for(i=0;i=4;i+)for(j=0;j=4;j+)Printf(“%d,%c”,aij,j-4?:n);,#includemain()inta55=1,2,25,i,j,t;for(i=0;i=4;i+)for(j=0;j=4;j+)t=aij;aij=aji;aji=t;for(i=0;i=4;i+)是否正确?for(j=0;j=4;j+)printf(%d,%c,aij,j-4?:n);,思考题:求矩阵中最大元素的值及其所在位置?,杨辉三角形,打印出以下的杨辉三角形。,111211331464115101051,用一维数组,用二维数组,二维数组实现,#includemain()inta1111,i,j,n;a11=1;a21=1;a22=1;scanf(%d,一维数组实现,#includemain()inta11,i,j,k,n,ij,m;scanf(%d,字符数组的定义,格式,char数组名常数1常数2;,举例,charc10;,c0=I;c1=;c2=a;c3=m;c4=;c5=h;c6=a;c7=p;c8=p;c9=y;,字符数组的初始化,将逐个字符赋给数组中各元素。charc10=I,a,m,h,a,p,p,y;花括号中初值的个数大于数组长度,则按语法错误处理。,字符数组的引用,说明,引用字符数组中的一个元素,即得到一个字符。,举例,输出一个字符串。,main()charc10=I,a,m,h,a,p,p,y;inti;for(i=0;i=9;i+)printf(%c,ci);printf(n);,字符串和字符串结束标志,提示,在C语言中无字符串数据类型,将字符串作为字符数组处理。,有效字符串,字符数组中,第一个字符串结束标志(0)前的字符串,称为有效字符串。,举例,有效字符串为:China存储字符串China时,a后自动加0。,字符数组赋初值补充,由于字符串在内存中存储时,后边自动加0,字符数组初始化可为:,charc=Iamhappy;,也可为:,charc=Iamhappy;,与下面的语句等价吗?,charc=I,a,m,h,a,p,p,y;,字符数组赋初值补充,用二维字符数组可存放多个字符串,第二维的长度表示字符串的长度,不能省略,应按最长的字符串长度设定;第一维的长度代表要存储的字符串的个数,可以省略。,charweekday710=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;可写成:charweekday10=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;不能写成:charweekday=Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;,字符数组与字符串的关系,1.字符串是采用字符数组来表示的,只是在有效字符串后自动加字符串结束标志0。2.字符数组不是字符串,只有当字符型一维数组中的最后一个元素值为0时,它才构成字符串。3.对于一个字符串常量,那么这个字符串常量本身代表的就是该字符串在内存中所占连续存储单元的首地址,是一个地址常量。4.如果将字符串赋值给了一个一维数组,那么这个一维数组的名字就代表这个首地址。,字符串的输入和输出,利用循环,逐个字符输入输出。,用格式赋%c输入或输出一个字符。,将整个字符串一次输入或输出。,用格式赋%s输入或输出一个字符串。,字符串输入,字符串输出,scanf函数对数组元素逐个进行输入。charc10;for(i=0;istr2,函数值为正整数;str1str2,函数值为负整数。,格式,integer:strcmp(,举例,charc110=abc,c28=abd;strcmp(c1,c2);值为负数,说明,不能用str1=str2来判str1和str2相等。,字符串长度函数-strlen,功能,测试有效字符串长度。,格式,integer:strlen(,举例,charc10=China;strlen(c);结果不是10和6,而是5,说明,也可以直接测试字符串常量。strlen(China);,字符串小写函数-strlwr,功能,将字符串中大写字母转换成小写字母。,格式,举例,charc10;strlwr(c);,说明,此函数将str中的大写字母转换成小写字母,同时将str的指针返回。charc10=China;strlwr(c);结果为:china,字符串大写函数-strupr,功能,将字符串中小写字母转换成大写字母。,格式,举例,charc10;strupr(c);,说明,此函数将str中的小写字母转换成大写字母,同时将str的指针返回。charc10=China;strupr(c);结果为:CHINA,字符数组程序举例-1,输入一个字符串,统计其中字符的个数,再把它们颠倒过来,然后输出。,解法1,解法2,解法3,解法1,#includemain()charc120,c;intn,i;scanf(%s,c1);n=strlen(c1)-1;for(i=0;i=n;i+)c=c1i;c1i=c1n-i;c1n-i=c;printf(n=%dnstring=%sn,n+1,c1);,正确吗?,解法2,#includemain()charc120,c;intn,i;scanf(%s,c1);n=strlen(c1)-1;for(i=0;i=n/2;i+)c=c1i;c1i=c1n-i;c1n-i=c;printf(n=%dnstring=%sn,n,c1);,#includemain()charc120,c;intn,i,j;scanf(%s,c1);n=strlen(c1)-1;for(i=0;in;i+,n-)c=c1i;c1i=c1n;c1n=c;printf(n=%dnstring=%sn,n,c1);,解法3,字符数组程序举例-2,有三个字符串,要求找出最大者。,数据结构:,C0,C1,C2,#includemain()charc320,str20;inti;for(i=0;i=2;i+)gets(ci);strcpy(str,c0);if(strcmp(str,c1)0)strcpy(str,c1);if(strcmp(str,c2)0)strcpy(str,c2);printf(nthelargeststring:n%sn,str);,指针,5.2.1.指针的概念5.2.2.为什么引入指针的概念5.2.3.变量的指针与变量的指针作为函数参数5.2.4.字符指针*5.2.5.字符指针作为函数参数,指针的概念,1.什么是变量的地址?什么是变量的内容?2.什么是直接寻址?什么是间接寻址?3.取地址运算符,取地址运算符,格式,得到某一变量存储空间的首地址。,2002,2003,变量A,内容,设P为指向整形的指针变量,2002,2003,变量A,内容,*P的运算结果是476。即是变量A的内容。,p=p初始化,指针P,*P和变量A作用是等价的。,为什么引入指针的概念,指针提供通过变量地址访问变量的手段。指针为C的动态内存分配系统提供支持。指针为动态数据结构(例如链表、队列、二叉树等)提供支持,操作系统的编写。指针可以改善某些子程序的效率。,现实中地址的例子:Email地址、寝室号、手机GPS定位系统(关机),本质:变量是通过变量地址来访问的。,进一步说明指针重要性,任意从键盘输入两个整数,编程将其交换后再重新输出。,(输出结果是否正确),进一步说明指针重要性,main()voidswap(intx,inty);inta,b;printf(Pleaseentera,b:);scanf(%d,%d,a,b没有进行交换,出错原因,15,8,main函数,a,b,15,8,swap函数,x,y,temp,调用swap函数,15,8,a,b,15,8,x,y,temp,执行swap函数,15,15,8,15,8,a,b,x,y,temp,从swap函数返回,8,15,15,变量的指针和指针变量,变量指针,指针就是地址,变量的指针就是变量的首地址。,指针变量,就是C语言中专门用于存放地址型数据的变量。,一般情况下,指针变量中的地址是内存中另一个普通变量的首地址。如果一个指针变量中存放的是另一个变量的首地址,我们就称第一个变量是指向第二个变量的指针。,指针变量的定义,由于变量有类型之分,指向变量的变量指针也有类型之分。,格式,类型*变量1,*变量2,;,举例,int*p1,*p2,n;float*p3,*p4,f;,P1=,说明,无指向,指向n,指针变量前面的*号,表示该变量的类型为指针型变量。不是进行指针运算。,在定义指针变量时,必须指定基类型。是由于指针型变量有运算:使指针加1;使指针移到下一位置。,符号*在变量说明语句中是个指针类型的说明符,前面的类型关键字用于说明指针可以指向哪一种类型的变量,我们称其为指针的基类型。,指针变量必须先定义,后使用。,指针变量的引用,一般变量只能存放数据,而不能存放变量的地址;指针变量只能存放变量的指针,即变量首地址,必须用相同基类型的变量的地址对其进行赋值。intn,*p;p=n;p=,与指针变量有关的两个特殊运算符:*:间接访问运算符。此时*p和n表示的是同一变量。,指针变量必须经初始化后才能使用,否则指针变量所指向的存储单元是不确定的,对其所作的赋值等操作将是很危险的。,由于指针的值就是地址,因此,指针运算实质上就是对地址的运算。因此,指针运算只能参与赋值运算、算术运算和关系运算。其中,指针可参与的算术运算只有两种:加和减,即加、减一个整数或自增、自减运算。+p表示指向下一个变量。-p指向上一个变量。,运算符*和+、-优先级等同,连续运算,采用右结合。下列各语句的含义如下:a=*p+先运算p+,但为后增运算,因而先将*p的值赋给a,然后p加1。a=(*p)+先取*p的值,赋给a。然后将p所指向的变量内容加1。,指针变量作函数参数,传递方式,属于赋地址调用,将实元指针传给虚参,虚参也是一指针。,虚参要求,必须是指针变量。,实参要求,是指针变量、数组名。,哑实结合,在哑实结合时,实元指针将其地址值传给哑元指针。,程序举例2,输入两个整数,按从大到小顺序排序。,#includevoidswap(int*p1,int*p2)intp;p=*p1;*p1=*p2;*p2=p;main()inta,b,*px1,*px2;scanf(%d,%d,swap函数的几种错误形式,voidswap(intx,inty)intt;t=x;x=y;y=t;,voidswap(int*p1,int*p2)int*p;p=p1;p1=p2;p2=p;,voidswap(int*p1,int*p2)int*p;*p=*p1;*p1=*p2;*p2=*p;,交换后变量值不能返回,交换后的指针的值也不能被返回,中间变量*p无存储空间,输入a和b两个数,按先小后大的顺序输出a和b。(要求不能改变a和b的值),指针的程序举例,#includemain()int*p1,*p2,*p,a,b;scanf(%d,%d,程序举例31,任意从键盘输入10个整数,然后对它们由小到大进行排序,并将排序后的结果输出,要求用形参为指针的函数编程实现排序和数组元素的输出。,#includevoiddisplay();voidsort();main()intt10,i;printf(Inputtennumbers:n);for(i=0;i10;i+)scanf(%d,程序举例32,voidsort(int*a,intn)inti,j,k,temp;for(i=0;in-1;i+)k=i;for(j=i+1;jn;j+)if(*(a+j)*(a+k)k=j;if(k!=i)temp=*(a+i);*(a+i)=*(a+k);*(a+k)=temp;Voiddisplay(int*a,intn)inti;for(i=0;in;i+)printf(%d,*(a+i);,程序举例41,用函数实现,将一个nn矩阵转置并输出。,#includevoidget_matrix(int*p,intn);voidput_matrix(int*p,intn);voidconvert(int*p,intn);#definem3main()intamm;printf(Input%d%dmatrix:n,m,m);get_matrix(a,m);convert(a,m);printf(Theconvertedmatrix:n);put_matrix(a,m);,程序举例42,get_matrix(int*p,intn)int*q;for(q=p;qp+n*n;q+)scanf(%d,q);,put_matrix(int*p,intn)int*q;for(q=p;qp+n*n;q+)if(q-p)%n=0)printf(n);printf(%d,*q);,程序举例43,voidconvert(int*p,intn)inti,j,temp;for(i=1;in;i+)for(j=0;ji;j+)temp=*(p+i*n+j);*(p+i*n+j)=*(p+j*n+i);*(p+j*n+i)=temp;,字符指针,定义,就是指向字符型数据的指针变量。,作用,使用字符指针可以指向一个字符串。,使用数组表示字符串与字符指针表示字符串的区别,定义方法不同:charstr10;/*定义的是一个字符数组。*/char*ptr;/*定义的是一个字符指针。*/,初始化含义不同:charstr10=China;表示定义一个字符数组str,前5个元素分别赋初值为C、h、i、n、a,后面的5个元素赋初值为0,字符串”China”在内存中存放的首地址就是数组的数组名str。,初始化含义不同:char*ptr=China;表示定义字符指针变量ptr,并在定义时用字符串China在内存中的首地址为指针变量ptr赋初值。,赋值方法和含义不同:char*ptr,str10;ptr=“China”;字符串的首地址赋给了ptr。,赋值方法和含义不同:char*ptr,str10;str=China;数组名代表的是数组的首地址,是一常量,因此,不能用赋值方法。将字符串赋给字符数组必须使用函数strcpy。,输入字符串时不同:char*ptr,str10;scanf(%s,str);用字符指针输入字符串时,必须确保字符指针事先已指向了一个数组的首地址。ptr=str;,字符数组的数组名是一个地址常量,它的值是不能改变的,而字符指针是一个变量,它的值是可以改变的。,字符数组可用于存放字符串,直接通过数组元素存取字符串属于直接寻址,字符指针则属于间接寻址。,字符指针变量和字符数组,#includemain()char*str=IloveChina!;str=str+7;printf(%s,str);,运行结果为:,China!,#includemain()char*str;str=IloveChina!;str=str+7;printf(%s,str);,字符指针作为函数参数,传递方式,属于赋地址调用,将实参字符指针传给虚参,虚参也是字符指针。,虚参要求,必须是字符指针。,实参要求,可为另一字符指针名。,哑实结合,哑实字符指针具有相同的首地址,即哑实字符串第一个字符占用同一存储单元,以后各字符按顺序一一结合。,程序举例,试编写字符处理函数,mid(s,s1,m,n)截取函数Left(s,s1,n)左截函数Right(s,s1,n)右截函数,mid函数,char*mid(char*s,char*s1,intm,intn)inti;for(i=m-1;im+n-1;i+)*(s1+i-m+1)=*(s+i);*(s1+n)=0;return(s1);,left函数,char*left(char*s,char*s1,intn)inti;for(i=0;in;i+)*(s1+i)=*(s+i);*(s1+n)=0;return(s1);,right函数,char*right(char*s,char*s1,intn)inti,m;m=strlen(s);for(i=0;in;i+)*(s1+i)=*(s+m-n+i);*(s1+n)=0;return(s1);,指针和数组间的联系,一个变量有地址,数组中包含的若干元素也有地址,指针变量即可指向变量,当然也可指向数组元素和数组。,指针的算术运算和关系运算常常是针对数组中的元素而言的。指向同一数组中不同元素的两个指针的关系运算是比较所指元素在数组中的前后位置关系。而指针的算术运算则是移动指针的指向,使其指向数组中的其它元素。,在表达式中,数组名被自动转化为指向数组中第一个元素的常量指针。,指针和数组间的联系,一维数组的地址和指针二维数组的地址和指针二维数组的行指针,一维数组的地址和指针,数组的指针,元素的指针,数组的起始地址。,数组元素的起始地址。,inta5,*p;,30003002300430063008,将第i个元素地址赋给p:p=,p=,等价,将数组地址赋给p。,int*p=,等价于,int*p;p=,不等价于,int*p;p=,赋初值:,通过指针引用数组元素,如果指针变量p指向数组某元素,则有如下运算:、。运算单位:元素序号。举例:int*p,a10;p=地址2000+pp指向a5、地址:2002-pp指向a3、地址:1998p+3p指向a7、地址:2006p-3p指向a1、地址:1994,当p的初值为a0,则有:p+i和a+i就是ai的地址,即指向a数组的第i个元素。第i个元素地址为:add=a+i*d其中:d为数组元素类型所占的字节数。指向数组的指针变量也可以带下标,例如:pi与*(p+i)等价。,引用一个数组元素,可以用:下标法:ai形式;指针法:(a+i)或*(p+i),当有:inta10,*p;p=时,是合法的,系统是按*(a+10)处理,即先找出(a+10)的值(是一个地址)然后找出它所指向的单元的内容。,*p+与*(p+)等价:先引用,后加1。*(p+)与*(+P)的作用不同。后者是先加1,后引用。(*P)+表示将p指向的元素值加1。,虽然a和p都指向了数组的首地址,但数组名a是个地址常量,不能通过赋值操作改变它的值,指针变量p是个变量,可以通过赋值运算改变它的值,从而使p指向数组中的其它元素。,虽然p+1和p+都指向当前指针所指单元的下一个元素,但p+1并不改变当前指针的指向,p仍然指向原来所指向的元素,而p+相当于执行p=p+1,因此p+操作改变了指针p的指向,表示将指针变量p向下移动一个元素位置,即指向下一个元素。,p+1并非将指针变量p的值简单的加1个字节,事实上,它是加上1*sizeof(基类型),这里,基类型为int,因此,每执行一次p+1就相当p加上2个字节。,数组元素的输入输出方法,下标法引用数组元素数组名法引用数组元素指针变量法引用数组元素通过指针变量自增运算引用数组元素!指针的下标表示法引用数组元素,下标法引用数组元素,main()inta10,i;for(i=0;i10;i+)scanf(“%d”,数组名法引用数组元素,main()inta10,i;for(i=0;i10;i+)scanf(“%d”,a+i);for(i=0;i10;i+)printf(“%d”,*(a+i);,指针变量法引用数组元素,main()inta10,*p,i;p=a;for(i=0;i10;i+)scanf(“%d”,p+i);for(i=0;i10;i+)printf(“%d”,*(p+i);,通过指针变量自增运算引用数组元素,main()inta10,*p;for(p=a;pa+10;p+)scanf(“%d”,p);for(p=a;pa+10;p+)printf(“%d”,*p);,自增运算执行效率高,利用自增运算代替了指针的算术操作,实现了指针的移动,其余算法效率相同.,指针的下标表示法引用数组元素,main()inta10,*p,i;p=a;for(i=0;i10;i+)scanf(“%d”,数组元素的举例,#includemain()inta4,*p,*p1,data1,data2;a0=1;a1=10;a2=20;a3=30;printf(%dt%dt%dt%dtn,a0,a1,a2,a3);p=a;p1=p;printf(a=%utp=%ut*p=%dn,a,p,*p);data1=*p+;data2=(*p)+;printf(*p+=%dt(*p)+=%dn,data1,data2);data1=*+p;data2=+*p;printf(*+p=%dt+*p=%dn,data1,data2);printf(p=%utp-p1=%dn,p,p-p1);printf(%dt%dt%dt%dtn,a0,a1,a2,a3);,求下列程序输出结果:,#includemain()inta4,*p,*p1,data1,data2;a0=1;a1=10;a2=20;a3=30;printf(%dt%dt%dt%dtn,a0,a1,a2,a3);,1102030,p=a;p1=p;printf(a=%utp=%ut*p=%dn,a,p,*p);,a=65488p=65488*p=1,data1=*p+;data2=(*p)+;printf(*+p=%dt(*p)+=%dn,data1,data2);,*p+=1(*p)+=10,1112030,printf(p=%utp-p1=%dn,p,p-p1);,P=65492p-p1=2,printf(%dt%dt%dt%dtn,a0,a1,a2,a3);,1112130,data1=*+p;data2=+*p;printf(*+p=%dt+*p=%dn,data1,data2);,*+p=20+*P=21,1112030,指针与多维数组,=,=,=,(2000),(2008),(2016),a,a0,a0+1,a0+2,a0+3,inta34=1,3,5,7,9,11,13,15,17,19,21,23,数组行指针,元素地址:,a+1,a+2,二维数组元素地址计算表,二维数组元素aij的4种等价表示形式,1.aij2.*(ai+j)3.*(*(a+i)+j)4.(*(a+i)j,P192,程序举例1,#defineFORMAT%d,%dnmain()inta34=1,3,5,7,9,11,13,15,17,19,21,23;printf(FORMAT,a,*a);158,158a数组的指针,*a是a0首地址printf(FORMAT,a0,*(a+0);158,158*a相当于*(a+0)printf(FORMAT,166,166,a是数组指针*a是行指针,printf(FORMAT,9,9*(a+1)是a10,程序举例2,用指针变量输出数组元素的值。,main()inta34=1,3,5,7,9,11,13,15,17,19,21,23;int*p;For(p=a0;pa0+12;p+)if(p-a0)%4=0)printf(n);printf(%4d,*p);,输出结果:,1357911131517192123,行指针(*p)N引用二维数组元素aij,1.pij2.*(pi+j)3.*(*(p+i)+j)4.(*(p+i)j,P195,程序举例3,main()inta34=1,3,5,7,9,11,13,15,17,19,21,23;int(*p)4,i,j;p=a;scanf(i=%d,j=%d,输出结果:,i=1,j=2a12=13,(*p)4是定义一个指针变量p,它指向包含4个元素的一维数组(行指针)。*p4是指针数组。,输出指定行、列的数组元素值。,字符指针变量和字符数组,字符数组由若干个元素组成,每个元素存放一个字符,而指针变量中存放的是地址(字符串首地址),绝不是将字符串放到字符指针变量中。,赋值方式:对字符数组只能对各个元素赋值,下列方法不正确。charstr14;str=IloveChina!;而对指针变量可采用下面方法赋值:char*a;a=IloveChina!;,对字符指针变量赋初值:char*a=IloveChina!;等价于:char*a;a=IloveChina!;而charstr14=IloveChina!;不等价于:charstr14;str=IloveChina!;,定义了一个字符数组,在编译时为他分配内存单元,有确切地址。而定义一个字符指针变量时,给指针变量分配内存单元(只能存放一个地址),没有实际的字符串存储单元。因而下面输入是很危险的。char*str;应为:char*a,str10;scanf(%s,str);a=str;scanf(%s,a);,指针变量的值是可以改变的。main()char*str=IloveChina!;str=str+7;scanf(%s,str);运行结果为:China!,指针数组,定义,由若干基类型相同的指针所构成的数组。一个数组,其元素均为指针数组。,格式,类型*数组名长度,举例,int*p4;,其中:p0,p1,p2,p3都是指针变量。,注明,int*p4;不能写成int(*p)4;这是指向一个一维数组的指针变量。,为什么使用指针数组,它适用于用来指定若干个字符串,使字符串处理更加灵活。,指向指针的指针,格式,类型指针名;,举例,char*p;,p=name+2;printf(%on,*p);printf(%sn,*p);,输出*p的地址值,输出*p所指字符串,inti;char*p;for(i=0;i5;i+)p=name+i;printf(%sn,*p);,一次输出若干字符串。,指针数组程序举例,将若干字符串按字典顺序(由小到大)输出。,#includemain()char*name=PASCAL,BASIC,FORTRAN,CLANGUAGE,DATASTRUCTURE;inti,j;char*temp;for(i=0;i0)temp=namei;namei=namej;nam

温馨提示

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

评论

0/150

提交评论