《C语言第10章(谭浩强).ppt》由会员分享,可在线阅读,更多相关《C语言第10章(谭浩强).ppt(80页珍藏版)》请在三一办公上搜索。
1、1,第10章 指针,指针可以有效地表示复杂的数据结构;能动态的分配内存、使用字符串和数组;能在调用函数时获得1个以上的结果;能直接处理内存单元地址等。掌握指针的应用,可以使程序简洁、紧凑、高效。,2,10.1 地址和指针的概念一、变量的地址计算机内存区的每一个字节都有一个编号。在对程序进行编译时,系统会给变量分配内存单元,这个内存单元的地址就是变量的地址。系统根据不同的数据类型分配不同字节的空间。,内存单元地址 内存单元内容 不同,编译时是把变量名转换为变量的地址如:scanf(“%d”,3,二、变量的访问方式1.直接访问 按变量地址存取变量值的方式称为“直接访问”方式。2.间接访问 假如定义
2、变量j 存放变量i的地址。,如:j=,4,三、指针变量 由于通过地址可以找到所需变量的存储单元,所以c语言把地址称为指针。指针:一个变量的地址称为该变量的指针。例如:地址2000是变量i的指针。指针变量:专门存放变量地址的变量叫指针变量。注意:指针和指针变量的区别如:j 为指针变量,它存放整型变量i的地址 我们称,指针变量 j 指向整型变量i,5,10.2 变量的指针和指向变量的指针变量变量的指针就是变量的地址。存放变量地址的变量是指针变量,用来指向另一个变量。,6,注意:在c程序中用*表示指向,若定义了i_pointer为指针变量,那么*i_pointer就是i_pointer指向的那个变量
3、。*i_pointer 相当于 i 都代表 3(值),/*指针i_pointer指向了变量i*/,一、如何定义一个指针变量形式:基类型*指针变量名指针只能指向基类型规定的类型变量例如:int i,j;float x;int*i_pointer,*j_pointer;那么,如何使一个指针变量指向另一个变量呢?可以:i=3;i_pointer=,7,在定义指针变量时注意:,(1)定义指针变量时,变量前面的*是表示该变量是指针型的,其变量名是i_pointer,而不是*i_pointer(2)定义指针变量必须指定其类型。为什么?当i_pointer+时,加1代表多少字节才能确定。总结:一个指针变量只
4、能指向同一类型的变量。如:float a;int*pointer;pointer=(错),8,二、指针变量的引用指针变量中只能存放地址(指针),两个运算符:1.,强调*定义和引用时的区别,9,输出:100,10 100,10,*pointer_1=,例10.1 通过指针变量访问整型变量main()int a,b;int*pointer_1,*pointer_2;/*区分定义和引用时的区别*/a=100;b=10;pointer_1=,10,说明:若:p1=p2=&a/*p2也指向了a*/(1)&*p1 的含义是什么?&和*优先级相同,按自右至左的方向结合,先进行*p1的运算,就是变量a,再执行
5、&运算。&*p1&a,(2)*&a 的含义是什么?先进行&a的运算,得a的地址,再进行*运算,就是变量a。*&a a 或*&a*p1,11,说明:若:p1=(3)(*p1)+a+(*p1)+必须有括号,若没有括号:*p1+/*优先级别相同,为右结合*/*(p1+)/*由于+在后,先使用p1,得到*p的值,p1再加1,p1指向了下一个地址*/,12,运行:5,9 a=5,b=9 max=9,min=5,注意:a和b并没有交换,保持原值,但是p1和p2的值改变了。,例10.2 输入a和b两个整数,按大小的顺序输出.main()int*p1,*p2,a,b;scanf(“%d,%d”,13,三、指针
6、变量作为函数参数 函数的参数可以是整型、实型、字符型等数据或者是数组,还可以是指针类型的。它的作用是将一个变量的地址传送到另一个函数中。,14,例10.3 同例10.2输入a和b两个整数,按大小的顺序输出.,main()int*p1,*p2,a,b;scanf(“%d,%d”,void swap(int*p1,int*p2)int temp;temp=*p1;*p1=*p2;*p2=temp;,/*指针变量作函数参数,把变量a和b的地址传给形参,这时实参和形参都指向变量a和b*/,/*定义形参,所以要带*/,/*把变量a和b的值交换*/,注意:a和b的值改变了。,15,指针变量作函数参数时,注
7、意:1.指针变量,既可以作为函数的形参,也可以作函数的实参。2.指针变量作实参时,与普通变量一样,也是“值传递”,即将指针变量的值(一个地址)传递给被调用函数的形参(必须是一个指针变量)。注意:被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值。,16,例10.4 输入a、b、c 3个整数,按大小顺序输出。,void swap(int*pt1,int*pt2)/*指针变量作函数形数*/int temp;temp=*pt1;*pt1=*pt2;*pt2=temp;/*交换变量*/,void exchange(int*q1,int*q2,int*q3)/*判断大小*/if(
8、*q1*q2)swap(q1,q2);/*指针变量作函数实参*/if(*q1*q3)swap(q1,q3);if(*q2*q3)swap(q2,q3);,main()int a,b,c,*p1,*p2,*p3;scanf(“%d,%d,%d”,17,10.3 数组的指针和指向数组的指针变量,既然指针可以指向变量,当然也能指向数组。数组的元素是连续存放的:一般,用下标法表示数组元素,如:a3,10.3.1 指向数组元素的指针 如何定义指向数组的指针变量?定义与指向普通变量的指针变量的定义方法一样。例如:int a10,*pointer=a;或者:int a10,*pointer;pointer=
9、a;以上是在语句中赋值,分为两步。,&a0,或,注意:如果数组为int型,则指针变量也必须为int型。,&a0,或,/*数组名代表数组的首地址*/,以上是在定义时赋值,18,int*p1,*p2,*p3;int a5=2,4,8,16,32;p1=,2,4,8,16,32,a0,a1,a2,a3,a4,p1,p2,p3,19,10.3.2 通过指针引用数组元素 如:int a3,*p=a;*p=1;/*相当于a0=1*/(p=1;)(错)注意:当p+1时,则指针p指向同一数组的下一个元素,而不是把地址加1。当p为int型时:p+1相当于使p的值(地址)加2个字节;当p为float型时:p+1相
10、当于使p的值(地址)加4个字节;所以:p+1代表的地址=p+1*d,/*d为数组元素的类型所占的字节数*/,20,说明:如果有 int a10,*p=a;,则:(1)p+i 和 a+i 都可以表示数组元素 ai 的地址,或者说它们都指向a数组的第i个元素。例如:p+9 a+9(2)*(p+i)和*(a+i)就是数组元素 ai 的值。例如:*(p+5)*(a+5),值都是&a9,都指向 a9/*是地址*/,都是 a5/*是值*/,实际上,在编译时,对数组元素ai是按*(a+i)处理的,若数组a的首地址为1000,a3的地址=1000+3*2=1006,再到地址1006找到a3的值。,21,说明:
11、(3)指向数组的指针变量,也可将其看作是数组名,因而也可按下标法来使用。例如:*(p+i)=p i=ai 所以:引用一个数组元素,可以用多种方法:1)下标法,如 ai 或 pi 形式;2)指针法,如*(a+i)或*(p+i),/*p是指针变量*/,/*a是数组名,p是指针变量*/,22,例10.5 输出数组中的全部元素。比较三种方法,(1)下标法void main()int a10,i;for(i=0;i10;i+)scanf(“%d”,(3)用指针变量指向数组元素void main()int a10,i,*p;for(i=0;i10;i+)scanf(“%d”,(2)用数组名计算数组地址,找
12、到元素的值void main()int a10,i;for(i=0;i10;i+)scanf(“%d”,第1、2种方法效率相同,第3种方法的效率更高,for(i=0,p=a;p(a+10);p+)printf(%d,pi);,23,使用指针变量指向数组元素时,需注意:(1)可以通过改变指针变量的值使其指向不同的元素,如 p+但是不能用数组名 a+(2)使用指针变量,要注意指针的当前值。如下例,main()int*p,i,a5;p=a;for(i=0;i5;i+)scanf(“%d”,p+);printf(“n”);,for(i=0;i5;i+,p+)printf(“%d”,*p);printf
13、(“n”);,p=a;,/*输出数组元素*/,解决办法:?,(3)由上例得出,指针变量可以指向数组以外的内存单元,系统不会报错。,24,*(p+)a0*(+p)a1,若 p a0,则,注意:(4)指针变量的运算。p=a;/*指针p指向了数组a的首地址*/1)p+/*使p指向下一个元素*/2)*p+*(p+)/*先得到*p的值,指针p指向下一地址*/如:for(i=0;i5;i+,p+)printf(“%d”,*p);3)*(p+)与*(+p)不同,可改为:for(i=0;i5;i+)printf(“%d”,*p+);,25,4)+(*p)/*p指向的值加1*/若 p a0,a0=5,则+(*p
14、)a0=65)若 p ai,则:*(p-)ai-/*先做*p运算,p再自减*/*(-p)a-i/*先做p自减,再做*运算*/*(+p)a+i同理,26,6)指针的关系运算 若两个指针指向同一个数组的元素,则可以进行关系运算,运算结果为0或1。、=:判断两个指针指向的数据位置的前后关系=,!=:判断两个指针是否指向同一个数据7)指针变量可以有空值,即该指针变量不指向任何变量。p=NULL;,27,10.3.3 用数组名作函数参数数组名作实参时:起始地址 形参数组;数组名作形参时:接收实参数组的起始地址实际上,c编译是把形参数组名作为指针变量来处理。如:f(int a,int n)f(int*a,
15、int n),等价,28,例10.7 请把数组a中的n个元素按相反的顺序存放。,算法:a0 an-1 a1 an-2 aint(n-1)/2 an-int(n-1)/2)-1,设循环变量i,ji=0;j=n-1 ai aj 交换;直到i=(n-1)/2。,i:0(n-1)/2(n-1):j-,29,main()int i,a10=3,5,2,6,8,9,0,1,7,4;for(i=0;i10;i+)printf(%d,ai);printf(n);inv(a,10);/*数组名a作实参*/for(i=0;i10;i+)printf(%d“,ai);,程序:,void inv(int x,int
16、n)/*数组名x作形参*/int temp,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-1-i;temp=xi;xi=xj;xj=temp;,void inv(int*x,int n)/*指针变量x作形参*/int temp,*i,*j,*p,m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i+,j-)temp=*i;*i=*j;*j=temp;,指针变量能否作形参?,30,总结:数组及指向数组的指针变量作函数参数时,可有种等价形式P238-239(本质上是一种,即指针数据作函数参数):(1)形参、实参都用数组名(2)形参、实参都用指针变量(3)
17、形参用指针变量,实参用数组名(4)形参用数组名,实参用指针变量,31,10.3.4 指向多维数组的指针多维数组元素的地址int a34=1,3,5,7,9,11,13,15,17,19,21,23,a数组包括3个元素:a0 a1 a2,而每个元素又是一个一维数组。因此:a a0 第0行&a00 a+1 a1 第1行&a10 a+2 a2 第2行&a20,可看作:,2000,a+1,2008,a+2,2016,1=8个字节,32,分析:第0行1列的地址表示?(&a01)a0 第0行 a0+1 第0行1列 1=2个字节(2002)第1行1列的地址表示?a1+1再分析:ai=*(a+i)或*(p+i
18、)或 pi 等价 a0=*(a+0)第0行(加1=8个字节)a0+1=*(a+0)+1 第0行第1列(加1=2个字节)结论:第i行j列的地址表示方法?ai+j或*(a+i)+j分析:第0行1列的值?地址:a0+1或*(a+0)+1值:*(a0+1)或*(*(a+0)+1)结论:aij的值?*(ai+j)或*(*(a+i)+j)总结:若a是一唯的,则ai表示第i个元素值;若a是二唯的,则ai表示第i行的首地址;,33,表10-2 二维数组a的性质,34,注意:对于二唯数组,为什么a+1和*(a+1)都是a1地址(2008)?a+1 第1行 a1/*数组名a是首地址*/对于二唯数组 a1=*(a+
19、1)a+1=*(a+1),35,#define FORMAT“%d,%dn”main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;printf(FORMAT,a,*a);printf(FORMAT,a0,*(a+0);printf(FORMAT,例10.10 输出二维数组有关的值,/*第0行首地址,0行0列元素地址*/,/*第0行0列元素地址*/,/*第0行首地址,第0行0列元素地址*/,/*第1行0列元素地址,第1行首地址*/,/*第1行0列元素地址*/,/*第2行0列元素地址*/,/*第2行首地址*/,/*第1行0列元素的值*/,36,2.指向多维数组的
20、指针变量(1)指向数组元素的指针变量例10.11 用指针变量输出数组元素的值。main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;int*p;for(p=a0;p a0+12;p+)if(p-a0)%4=0)printf(“n”);printf(“%4d”,*p);,/*a0代表第0行0列元素地址*/,37,aij在数组(n*m)中的相对位置计算公式:i*m+j(m为数组的总列数)如:a23 位置=2*4+3(2)指向由m个元素组成的一唯数组的指针变量 例10.11的指针变量p是指向整型数据的,p+1表示指向下一个元素。可以使p不指向整型数据,而指向包含m
21、个元素的一唯数组,这样p+1就表示下一行元素的首地址。,地址?,&a00+(2*4+3)*d,38,例10.13 输出二维数组任一行任一列元素的值。main()int a34=1,3,5,7,9,11,13,15,17,19,21,23;int(*p)4,i,j;p=a;scanf(“%d,%d”,/*表示p所指的对象是有4个整型元素的数组,p只能指向一个包含4个元素的一唯数组*/,*p,*(p+1),输入:1,1输出:11,更改后:输入:1,1输出:3,39,3.用指向数组的指针作函数参数例 10.13 有一个班,3个学生,4门成绩。求所有成绩的平均分,第2个学生的各门成绩。,average
22、(float*p,int n)float*p_end;float sum=0,aver;p_end=p+n-1;for(;p=p_end;p+)sum=sum+(*p);aver=sum/n;printf(average=%5.2fn,aver);,search(float(*p)4,int n)int i;for(i=0;i4;i+)printf(%5.2f,*(*(p+n)+i);,main()float score34=65,67,70,60,80,87,90,81,90,99,100,98;average(*score,12);search(score,2);,/*第0行0列元素地址,
23、即&score00*/,/*第0行的首地址,即&score0*/,40,10.4 字符串的指针和指向字符串的指针变量,10.4.1 字符串的表示形式在语言中,可用两种方法访问字符串。字符数组和字符指针(1)用字符数组存放字符串main()char string=“I love China!”;printf(“%s”,string);,第4个元素表示:string4=*(string+4)=v,41,(2)用字符指针指向字符串/*使用字符指针变量表示和引用字符串*/,char*string;string=“I love China!”;,/*把字符串的首地址赋给指针变量string,不是把字符串
24、的值赋给string.*/,*string=“I love China!”;错,/*定义字符指针指向字符串*/,main()char*string=“I love China!”;printf(“%s”,string);,42,例 10.17 把字符串a复制给字符串b,main()char a=“I am a boy.”,b20;int i;for(i=0;*(a+i)!=0;i+)*(b+i)=*(a+i);*(b+i)=0;printf(“string a:%s”,a);printf(“string b:%s”,b);,/*用指针法表示*/,main()char a=“I am a boy
25、.”,b20,*p,*q;int i;p=a;q=b;for(;*p!=0;p+,q+)*p=*q;*q=0;printf(“string a:%s n”,a);printf(“string b:%s”,b);,本例能用指针变量处理吗?,43,10.4.2 字符指针作函数参数 当要调用子函数处理字符串时,需把字符串的地址从主调函数传送到子函数时,可以用字符数组名或指针作为函数的参数。例10.10 用函数调用实现字符串的复制。法:1)用字符数组作参数,main()char a=“I am a teacher.”;char b=“you are a student.”;copy-string(a,
26、b);printf(“string a=%s n string b=%s”,a,b);,void copy_string(char from,char to)int i=0;while(from i!=0)to i=from i;i+;to i=0;,/*用字符数组名作实参*/,/*用字符数组作形参*/,44,注意:由于b数组原来的长度大于a数组,因此将a数组复制到数组b后,未能全部覆盖b数组原有内容。b数组最后3个元素仍保留原状。在输出时由于按%s(字符串)输出,遇到0即告结束,因此第一个0后的字符不输出。如果采用%c逐个字符输出是可以输出后面这些字符的。,45,2)用字符指针变量作形参,m
27、ain()char from=“I am a teacher.”;char to=“you are a student.”;char*a=from,*b=to;copy-string(a,b);printf(“string a=%s n string b=%s”,a,b);,void copy_string(char*from,char*to)for(;*from!=0;from+,to+)*to=*from;*to=0;,/*用字符指针作形参*/,/*用字符指针作实参*/,46,10.4.3 对使用字符数组和字符指针变量的讨论,(1)字符数组是由若干个元素组成,每个元素中放一个字符,而字符指
28、针变量存放的是字符串第1个字符的地址(首地址),不是把字符串存到指针变量中;(2)赋值方式不同;,char*a;a=“I love China!”;,/*数组名是首地址,看作常量*/可以在定义时赋初值,不可以在语句中直接赋值,/*赋给a的是字符串的首地址,不是字符串本身*/也可以在定义时赋值,char str14;str=“I love China!”;(错),char str=“I love China!”;,47,(3)如果定义了一个字符数组,可以通过以下方式输入数据。,char str 10;scanf(“%s”,str);,char*a;scanf(“%s”,a);,/*可行的*/,/
29、*可行但危险的,因为定义a时只是分配了变量a的地址,并没有定义a的值(指向)。所以当程序规模大时,容易出现“冲突”,并且编译时会有警告提示*/,char*a,str10;a=str;scanf(“%s”,a);,应改为:,48,(4)指针变量的值可以改变,例 10.20 改变指针变量的值,main()char*a=“I love China!”;a=a+7;printf(“%s”,a);,char s=“I love China!”;s=s+7;(错)/*数组名是常量,代表首地址*/printf(“%s”,s);,main()char*a=“I love China!”;printf(“%c”
30、,a5);/*用下标法引用指针变量*/,用下标法引用指针变量:,结果:China,/*改变了指针变量的值*/,49,(5)用指针变量指向一个格式字符串,用来代替printf函数中的格式字符串。如:char*format=“a=%d,b=%fn”;printf(format,a,b);,printf(“a=%d,b=%fn”,a,b);,相当于,char format=“a=%d,b=%fn”;printf(format,a,b);,也可用字符数组实现:,50,10.5 指向函数的指针 10.5.1 用函数指针变量调用函数编译时,函数被分配给一个入口地址(即函数的指针),可以用一个指针变量指向函
31、数,通过指针变量调用此函数。回顾函数调用方法例10.23 求a和b中的大者。,main()int max(int a,int b);int a,b,c;scanf(“%d,%d”,再看:用函数指针变量访问函数,max(int x,int y)int z;if(x y)z=x;else z=y;return(z);,等价于 c=max(a,b);,51,说明:(1)指向函数的指针变量的定义形式:数据类型(*指针变量名)(函数参数列表);/*数据类型是指函数返回值的类型*/(2)函数的调用可以用函数名,也可以用函数指针;(3)指向函数的指针变量可以先后指向同一类型的不同函数;(4)给函数指针变量赋
32、值时,只需给出函数名 如:p=max;p=max(a,b);(错)(5)用指针变量调用函数时,只需用(*p)代替函数名;如:c=(*p)(a,b);(6)指向函数的指针不能作 p+或 p+i 的操作。,/*表示调用p指向的函数,实参为a,b,函数返回值的类型,由指针变量p的数据类型决定*/,52,10.5.2 用指向函数的指针作函数参数 函数的参数可以是变量、指向变量的指针变量、数组名、指向数组的指针变量,另外函数的指针也可以作为函数的参数,即指向函数的指针变量作函数参数,是实现函数地址的传递。原理:假设,函数sub(x1,x2)形参x1和x2为指向函数的指针变量;调用函数sub时,假设实参为
33、两个函数名f1和f2,传给形参的是函数f1和f2的入口地址;这样,在函数sub中就可以调用函数f1和f2了。用指针实现了函数的嵌套调用。,53,f1()f2()void sub(int(*x1)(int),int(*x2)(int,int)int a,b,i,j;a=(*x1)(i);b=(*x2)(i,j);main()sub(f1,f2);,/*x1为形参,指向函数的指针变量,指向的函数只有一个参数*/,/*相当于a=f1(i),调用f1函数*/,/*实参为函数名,传递的是函数的入口地址*/,/*相当于a=f2(i,j),调用f2函数*/,例如:,54,用指针变量可方便的调用不同函数,实现
34、结构化程序设计。例 10.23 用一个函数process,第一次调用它时找出a和b的大数,第二次调用找出小数,第三次调用找出总和。,int max(int x,int y)int z;if(xy)z=x;else z=y;return(z);,int min(int x,int y)int z;if(xy)z=x;else z=y;return(z);,int add(int x,int y)int z;z=x+y;return(z);,void process(int x,int y,int(*fun)(int,int)int result;result=(*fun)(x,y);printf
35、(“%dn”,result);,void main()int a,b;scanf(“%d,%d”,/*函数的入口地址*/,55,10.6 返回指针值的函数,一个函数可以返回一个int型、float型、char型的数据,也可以返回一个指针类型的数据。返回指针值的函数(简称指针函数)的定义格式如下:函数类型*函数名(形参表)float search(float(*p)4,int n)float*tp;tp=*(p+n);return(tp);,56,cccccint*seek(int(*pnt_row)3)int i=0,*pnt_col;/*定义一个(列)指针变量pnt_col*/pnt_col
36、=*(pnt_row+1);/*使pnt_col指向下一行之首(作标志用)*/for(;i3;i+)if(*(*pnt_row+i)60)/*某项成绩不合格*/pnt_col=*pnt_row;/*使pnt_col指向本行之首*/break;/*退出循环*/return(pnt_col);,57,/*主函数main()*/main()int grade33=55,65,75,65,75,85,75,80,90;int i,j,*pointer;/*定义一个(列)指针变量pointer*/for(i=0;i3;i+)/*控制每个学生*/pointer=seek(grade+i);/*用行指针作实
37、参,调seek()函数*/if(pointer=*(grade+i)/*该学生至少有一项成绩不合格*/*输出该学生的序号和各项成绩*/printf(“No.%d grade list:”,i+1);for(j=0;j3;j+)printf(“%d”,*(pointer+j);printf(“n”);程序运行结果:No.1 grade list:55 65 75,58,程序说明:(1)主函数中的pointer=seek(grade+i);语句调用seek()函数时,将实参grade+i(行指针)的值,复制到形参pnt_row(行指针变量)中,使形参pnt_row指向grade数组的第i行。(2)
38、在指针函数seek()中:1)pnt_col=*(pnt_row+1);语句*(pnt_row+1)将行指针转换为列指针,指向grade数组的第i+1行第列,并赋值给(列)指针变量pnt_col。2)if(*(*pnt_row+i)60)行pnt_row是一个行指针,指向数组grade的第i行;*pnt_row使指针由行转换为列,指向数组grade的第i行列;*pnt_row+j的值还是一个指针,指向数组的第i行第j列;*(*pnt_rowj)是一个数据(数组元素gradeij的值)。,59,10.7 指针数组和指向指针的指针,10.7.1 指针数组的概念 一个数组,其元素均为指针类型数据,称
39、为指针数组。数组的每个元素都是一个指针数据。指针数组比较适合用于指向多个字符串,使字符串处理更加方便、灵活。定义格式:数据类型*数组名元素个数 例如:int*p4由于 比*优先级高,因此P先与4结合,形成P4形式,然后再与P前面的“*”结合,“*”表示此数组是指针类型的,每个数组元素相当于一个指针变量,都可指向一个整型变量。例:有若干计算机图书,请按字母顺序,从小到大输出书名。解题要求:使用排序函数完成排序,在主函数中进行输入输出。/*程序功能:指针数组应用示例*/,60,void sort(char*name,int count)char*temp_p;int i,j,min;/*使用选择法
40、排序*/for(i=0;i0)/*存在更小的串*/min=j;/*保存之*/if(min!=i)/*存在更小的串,交换位置*/temp_p=namei;namei=namemin;namemin=temp_p;,61,main()char*name5=“BASIC”,”FORTRAN”,”PASCAL”,”C”,”FoxBASE”;int i=0;sort(name,5);/*使用字符指针数组名作实参,调用排序 函数sort()*/for(;i5;i+)printf(“%sn”,namei);/*输出排序结果*/程序运行结果:BASIC C FORTRAN FoxBASE PASCAL,62,
41、程序说明:(1)实参对形参的值传递:sort(name,5);void sort(char*name,int count)(2)字符串的比较只能使用strcmp()函数。形参字符指针数组name的每个元素,都是一个指向字符串的指针,所以有strcmp(namemin,namej)。主函数main()的形参在以往的程序中,主函数main()都使用其无参形式。实际上,主函数main()也是可以指定形参的。案例:用同一程序实现文件的加密和解密。约定:程序的可执行文件名为lock.exe,其用法为:lock+|-,其中“+”为加密,“-”为解密。,63,main(int argc,char*argv)
42、ccccc char c;if(argc!=3)printf(参数个数不对!n);else c=*argv1;/*截取第二个实参字符串的第一个字符*/switch(c)case+:/*执行加密*/printf(执行加密程序段。n);/*加密程序段*/break;case-:/*执行解密*/printf(执行解密程序段。n);/*解密程序段*/break;default:printf(第二个参数错误!n);,64,1.主函数main()的有参形式 main(int argc,char*argv)2.实参的来源运行带形参的主函数,必须在操作系统状态下,输入主函数所在的可执行文件名,以及所需的实参,
43、然后回车即可。命令行的一般格式为:可执行文件名实参 实参2本程序的用法:lock+|-在TC的集成环境下,也可直接利用Options|Arguments 项,输入主函数所需要的实参:只须输入各参数(相邻参数间用空格分开),可执行文件名可省略。就本案例而言,输入“+|-”即可。,65,3.形参说明(1)形参argc是命令行中参数的个数(可执行文件名本身也算一个)。在本案例中,形参argc的值为3(lock、+|-、文件名)。(2)形参argv是一个字符指针数组,即形参argv首先是一个数组(元素个数为形参argc的值),其元素值都是指向实参字符串的指针。在本案例中,元素argv0指向第1个实参字
44、符串“lock”,元素argv1 指向第2个实参字符串“+|-”,元素argv2指向第3个实参字符串“被处理的文件名”。,66,10.7.2 指向指针的指针 指向指针数据的指针变量,简称为指向指针的指针。怎样定义一个指向指针数据的指针变量呢?形式:char*p;相当于*(*p),显然*P是指针变量的定义形式。现在又加一个*号,表示指针变量P是指向一个字符指针变量的。*P就是P所指向的另一个指针变量。,67,例10.28指向指针的指针的应用 main()char*name=“f0llowme”,”basic”,great wall”,”fortran”,computer design”);cha
45、r*p;int i;for(i=0;i5;i+)p=name+I;printf(“%sn”,*p);,68,指向指针的指针变量简介在案例的主函数main()中,数组name是一个字符指针数组,即数组的每一个元素都是一个指向字符串的指针。既然name是一个数组,则它的每一个元素也同样有相应的地址,因此可以设置一个指针变量pointer,使其指向指针数组的元素(元素的值还是一个指针),称pointer为指向指针的指针变量。显然,指向指针的指针变量是一个两级的指针变量。1.指向指针的指针变量的定义 数据类型*指针变量,*指针变量2;2.指向指针的指针变量的赋值 指针变量=指针数组名+i,69,例如1
46、0.29 指针数组的元素指向数据 main()static int a5=(1,3,5,7,9;int*num5=输出结果:,70,10.8 有关指针的数据类型和指针的小结 10.8.1 有关指针的数据类型的小结int i 定义整型变量iint*p;P为指向整型数据的指针变量int an;整型数组a有n个元素int*pn;P由n个指向数据的指针元素组成int(*p)n;P为指向n个元素的数组的指针变量int f();f为带回整型函数值的函数int*p();P为带回一个指针的函数,该指针 指向整数int(*p)();P为指向函数的指针,返回一个整型值 int*p;p指针变量指向整型数据的指针变量
47、,71,二 10.8.2 指针运算小结1)指针变量加、减:P+P-P+i P-i P+=i P-=等2)指针变量赋值:P=&Ap=array p=&arrayi p=max p1=p2 注意:不应把一个整数赋给指针变量3)指针变量可以有空值 如:P=NULL4)两个指针变量可以相减,假如p1指向a1,p2指向a4,则p2-p1=4-1=3。5)两个指针变量比较 p1p2,72,10.8.3 vold 指针类型定义一个指针变量,但不指定它是哪一个类型数据的。在赋给另一个指针变量时要加强制类型转换。如:char*p1;void*p2;p1=(char*)p2;void*指针类型是ANSI系统新加的
48、,若详细了解可参阅有关手册。,73,有以下程序#include main()int m=1,n=2,*p=程序运行后的输出结果是B A)1,2,1,2 B)1,2,2,1 C)2,1,2,1 D)2,1,1,2,74,有以下程序#include#include main()char str 20=“One*World”,“One*Dream!”,*p=str1;printf(“%d,”,strlen(p);printf(“%sn”,p);程序运行后的输出结果是C A)9,One*World B)9,One*Dream C)10,One*Dream!D)10,One*World,/*p指向了第1
49、行0列元素的地址*/,75,下列函数的功能是A fun(char*a,char*b)while(*b=*a)!=0)a+,b+;A)将a所指字符串赋给b所指空间 B)使指针b指向a所指字符串 C)将a所指字符串和b所指字符串进行比较 D)检查a和b所指字符串中是否有0,76,若有定义语句:int a410,*p,(*q)4;且0i4,则错误的赋值是B/*q是指向一维数组的指针*/A)p=a B)qi=ai C)p=ai D)p=&a21,77,有以下程序#include#include main()char a10=”abcd”;printf(“%d,%dn”,strlen(a),sizeof
50、(a);程序运行后的输出结果是B A)7,4 B)4,10 C)8,8 D)10,10,strlen(a)测定a中不包括0字符个数;sizeof(a)测定a所占的字节数。,78,设有以下函数 void fun(int n,char*s)则下面对函数指针的定义和赋值均是正确的是A A)void(*pf)();pf=fun;B)viod*pf();pf=fun;C)void*pf();*pf=fun;D)void(*pf)(int,char);pf=,79,设有定义:char*c;,以下选项中能够使字符型指针c正确指向一个字符串的是A A)char str=”string”;c=str;B)sca