《C语言程序课件ppt第8章指针》由会员分享,可在线阅读,更多相关《C语言程序课件ppt第8章指针(90页珍藏版)》请在金锄头文库上搜索。
1、第8章 指针引例引例: :A、B、C、三人欲借用某旅馆的房间。A先到达旅馆,在服务台登记了房间,房间号是5818。然后,A电话通知了B,但没有通知C,B和C怎样找到A呢?B可以直接到5818找到A(直接访问)。C可以从旅馆的服务台查询到A的房间号5818,再找到A。(间接访问)8.1 指针和地址一、变量的地址计算机中,数据存储在内存中。内存可划分为若干存储单元,每个单元可以存放8位二进制数,即一个字节。内存单元采用线性地址编码,每个单元具有唯一一个地址编码。1、变量地址:系统为变量分配的内存单元的地址。(一个无符号整型数)int a;float b;a=3;b=5 3 53AB03AB82、变
2、量的有关概念存储内容:数据值空间大小:数据类型空间位置:地址生存周期:存储类别二、变量的访问方式1、直接访问2、间接访问 3AB0 3AB8 3 5 3AB8如何定义如何定义P?如何获得变量如何获得变量b的地址?的地址?如何通过如何通过P访访问问b?abp8.2指针变量8.2.1指针变量的定义一、定义方法类型符 *指针变量名如:int *p1 ,*p2 ;char *ps; float *pf1,*pf2;指针变量的类型:所指向的内存中存放的数据的类型。二、注意事项(1)必须先定义后使用;(2)指针变量名是p1,p2,而不是*p1,*p2;(3)一个指针变量只能指向同类型的变量;(4)定义指针
3、变量时,不仅要定义指针变量名,还必须指出指针变量所指向的变量的类型.8.2.2指针变量的赋值指针变量的值为地址,是一个无符号整数。但不能直接将整型常量赋给指针变量。P1=12345u.(1)用变量的地址给指针变量赋值(求地址运算符&)如:int a,b,*p;p=&a;注意:变量的类型必须与指针变量的相同。(2)用相同类型的指针变量赋值。如:int a;int *p1,*p2;p1=&a;p2=p1;注意:若不赋值,则指针变量的值是随机的。(3)赋空值NULL如:P=NULL;或P=0;例8-1通过指针变量访问整型变量.#include void main( ) int x; int *p1;
4、x=8;p1=&x;printf(“%dn”,x);printf(“%dn”,*p1);例8-2通过指针变量求两个整数的和与积.#include void main( ) int i=100,b=200,s,t,*pi,*pb;pi=&i;pb=&b;s=*pi+*pb;t=*pi*pb;printf(“i=%dnb=%dni+b=%dni*b=%dn”,i,b,i+b,i*b);printf(“s=%dnt=%dn”,s,t);例8-3通过指针变量求三个整数中的最大数和最小数.#include void main( ) int a,b,c,*pmax,*pmin;printf(input t
5、hree numbers:n);scanf(%d%d%d,&a,&b,&c);if(ab)pmax=&a;pmin=&b;else pmax=&b;pmin=&a;if(c*pmax) pmax=&c;if(c*pmin) pmin=&c;printf(max=%dnmin=%dn,*pmax,*pmin);8.2.3指针运算符和指针表达式1、两个相关的运算符:*,&形式:&任意变量 /*取地址运算符*/ *指针变量 /*指针运算符*/含义:&a表示变量a所占据的内存空间的首地址. *p表示指针变量p所指向的内存中的数据.应用:通过指针变量访问所指变量.将指针变量指向被访问的变量.如:int
6、a=5,*p,b;p=&a;访问所指变量取内容:b=*p;printf(“%dn”,*p);存内容:*p=100; 2、运算规则 *,&:优先级相同,且右结合 注意:与+,-,!等单目运算符的优先级相同,高于算术运算符*,/,%。 如有:void main ( ) int a=2,*p=&a,*q=&a; printf(%d,%dn,*p+,*(q+); p=&a;q=&a; printf(%d,%dn,*p,(*q)+); printf(%d,%dn,*p,+*q); 结果是:2,2 2,2 4, 4 写出下面表达式的结果,并找出具有等价关系的对子 int a=5,*p=&a; &*p *&
7、a (*p)+ &a a *p+ *(p+) a+思考:下列表达式是何含义?有什么要求?&*p,*&a8.2.4指针变量引用*指针变量例8-4 用指针变量进行输入和输出.void main( ) float *pi,x;scanf(“%f”,&x);pi=&x;printf(“%f”,*pi);例8-5:#include void main()int a=5,b=3;int *p;p=&a; /*指针变量赋值*/b=*p+5;printf(%dn,b);*p=4;printf(%d,%dn,a,*p);结果:10 4,4注意:*p若出现在 “=“的右边或其它表达式中,则为取内容. *p若出现在
8、 “=“的左边则为存内容&a&b95p2p1ba&b&a95p2p1ba改为:c=a;a=b;b=c;&a&b59p2p1ba程序中改变的是指针变量的值,而变量本身没变化;相当只调整房间号,而未惊动客人例例.8-6 输入输入a和和b两个整数,两个整数,按先大后小的顺序输出按先大后小的顺序输出#include #include void main()void main()int *p1,*p2,*p,a,b;int *p1,*p2,*p,a,b;scanf(%d,%d,&a,&b);scanf(%d,%d,&a,&b);p1=&a;p2=&b;p1=&a;p2=&b;if (ab)if (ab)
9、p=p1,p1=p2,p2=p;p=p1,p1=p2,p2=p;printf(a=%d,b=%dn,a,b);printf(a=%d,b=%dn,a,b);printf(max=%d,min=%d,*p1,*p2);printf(max=%d,min=%d,*p1,*p2);运行结果运行结果:5,9:5,9a=5,b=9a=5,b=9max=9,min=5max=9,min=5例例8-78-7读程序读程序#include #include void main( )void main( )int a,b,c;int a,b,c;int *pa,*pb,*pc;int *pa,*pb,*pc;pa
10、=&a;pb=&b;pc=&c;pa=&a;pb=&b;pc=&c;scanf(%d%d,pa,pb);scanf(%d%d,pa,pb);printf(a=%d,b=%dn,*pa,*pb);printf(a=%d,b=%dn,*pa,*pb);c=a+b; printf(c=%dn,*pc);c=a+b; printf(c=%dn,*pc);*pc=a+*pb; printf(c=%dn,c);*pc=a+*pb; printf(c=%dn,c);c=*pa*pb; printf(c=%dn,c);c=*pa*pb; printf(c=%dn,c);c=+*pa+(*pb)+; print
11、f(c=%dn,c);c=+*pa+(*pb)+; printf(c=%dn,c);c=(*pa)+ +*pb; printf(c=%dn,c);c=(*pa)+ +*pb; printf(c=%dn,c);printf(a=%d,b=%dn,a,b);printf(a=%d,b=%dn,a,b);结果:结果:例:交换例:交换a,ba,b两个数两个数#include #include void main( )void main( ) int a=5,b=8; int a=5,b=8; int t; int t;printf(a=%db=%dn,a,b);printf(a=%db=%dn,a,b
12、);t=a;a=b;b=t;t=a;a=b;b=t;printf(a=%d b=%dn,a,b);printf(a=%d b=%dn,a,b); 例:交换例:交换a,ba,b两个数两个数#include #include void main( )void main( ) int a=5,b=8; int a=5,b=8; int *pa=&a,*pb=&b; int *pa=&a,*pb=&b; int t; int t;printf(a=%d b=%dn,a,b);printf(a=%d b=%dn,a,b);t=*pa;*pa=*pb;*pb=t;t=*pa;*pa=*pb;*pb=t;p
13、rintf(a=%d b=%dn,a,b);printf(a=%d b=%dn,a,b); 8.2.5 指针变量作为函数参数主函数的实参与函数中的形参均为指针变量,互相传递的是指针变量,属“单向地单向地址值传递址值传递 ”.在被调函数中,如果改变的是变量,则影响主函数 若改变的是指针的指向,则不影响主函数以前未用指针变量时,函数调用时,实参与形参相当于不同房间住着相同的人,彼此互不影响,只从被调函数返回一个值return59959abcxy例如例如指针变量作函数参数时,主函数可以从被调函数得到多个返回值,函数可以不要return()语句了。方法:1.在主函数中设n个变量, 用n个指针变量指向它
14、们;2.然后将指针变量作为实参,将这n个变量的地址传给被调函数的形参;3.通过形参指针变量,改变这n个变量的值;4.主函数中就可以使用这些改变了值的变量;例子8.3指针与数组8.3.1指向数组的指针1、数组是连续存放的若干元素的集合;2、数组名就是指向此数组第一个元素的指针(首地址);如:int a =1,3,5,7;int *p;p=a;3、某个元素的地址:p=&a0用指针引用该元素:*p等价于ai4、数组元素的地址在内部实现时,统一按“基地址+位移”的方式处理。即a,a+1,a+i1357&a0pa0a1a2a3故表示数组元素的地址可以用:故表示数组元素的地址可以用:p+i,a+ip+i,
15、a+i表示数组元素的内容可以用:表示数组元素的内容可以用:aiai、* *(p+i)(p+i)、* *(a+i)a+i)注意:数组名注意:数组名a a(数组的指针)与指向数组首地址的指针变量(数组的指针)与指向数组首地址的指针变量p p不不同,同,a a不是变量。不是变量。例例8-108-10读程序,写出结果。读程序,写出结果。 void main( )void main( )int i,a5;int i,a5;int *p;int *p;for(i=0;i5;i+)for(i=0;i5;i+)p=&ai;p=&ai;ai=i;ai=i;printf(%3d,*p);printf(%3d,*p
16、);printf(n);printf(n);结果:结果:0 1 2 3 40 1 2 3 4 void main( )void main( )int i,a5;int i,a5;int *p=a;int *p=a;for(i=0;i5;i+,p+)for(i=0;i5;i+,p+)*p=i;*p=i;printf(%3d,*p);printf(%3d,*p); printf(n);printf(n);结果:结果:0 1 2 3 40 1 2 3 4 地址关系 内容关系8.3.2 通过指针引用数组元素通过指针引用数组元素数组指针、指针变量与数组元素之间的关系。数组指针、指针变量与数组元素之间的关
17、系。设设int a10,*p=a;则则&a0a0a1a2a3*a*(a+1)*(a+2)*(a+3)*p*(p+1)*(p+2)*(p+3)&a1&a2&a3pp+1p+2p+3aa+1a+2a+3p0p1p2p3例8-11任意输入10个数,将这十个数按逆序输出(1)用下标法访问数组#include void main()int a10,i;for(i=0;i=0;i-)printf(%d ,ai);(2)用数组名访问数组)用数组名访问数组#include void main()int a10,i;for(i=0;i=0;i-)printf(%d ,*(a+i);(3)用指针变量指向数组元素)
18、用指针变量指向数组元素方法一:#include void main()int a10,i,*p;for(i=0;i=0;i-)printf(%d ,*(p+i);方法二:#include void main()int a10,i,*p;p=a;for(i=0;i=a;p-)printf(%d ,*p);上述三种方法的比较上述三种方法的比较: 例8-11中,和(3)中的“方法一”执行效率是相同的,编译系统需要将ai转换成*(a+i)处理的,即先计算地址再访问数组元素。“方法二”执行效率比其它方法快,因为它有规律地改变地址值的方法(p-)能大大提高执行效率。 要注意指针变量的当前值。几个要注意的问
19、题:几个要注意的问题: int a10=1,2,3,4,5,6,7,8,9,10, *p; for (p=a;a(p+10);a+) printf (%dn,*a); int a10=1,2,3,4,5,6,7,8,9,10, *p=a; for (;p(a+10);p+) printf (%dn,*p); 指针变量(指针变量(p)值自身可以改变,值自身可以改变,但数组名但数组名(a)不能。不能。p是一个指针变量,是一个指针变量,p+ +合法;合法;而而a是一个数组名,是常量,是一个数组名,是常量,a+ +不合法。不合法。要注意指针变量的当前值;如void main() int *p,i,a1
20、0; p=a;for (i=0;i10;i+ +) scanf(“%d”,p+); for (i=0;i10;i+ +,p+) printf(“%d”,*p); 试分析此程序错在哪里?试分析此程序错在哪里?执行完第一个循环执行完第一个循环,p已指向数组的末尾了。如:已指向数组的末尾了。如:有有p=a;后;后a+1与与p+1指向同一个地址;当有指向同一个地址;当有p=b;后;后a+1与与p+1指向不同地址。指向不同地址。p=a;指针变量的运算p=a p+ + ;p=p+1 或p+=1, p指向a1等效*(p+),取出p指向的元素的值,p指向下一元素例如*(+p), 先p指向下一元素取出p指向的元
21、素的值,例如取出p指向的元素的值,p指向的元素加1(*p)+ +*p+ + ;*(+p)如果p当前指向a 数组的第i个元素。则:*(p-)相当于 ai-*(+p) 相当于 a+i*(-p) 相当于 a-i想输出a数组100个元素p=a;while(pa+100)printf(%d,*p+);p=a; while(pa+100) printf(%d,*p); p+;例例8-128-12将数组将数组a a的数据复制到数组的数据复制到数组b b中并输出。中并输出。( (用三种用三种方法实现方法实现) )#define M 7#define M 7void main( )void main( )int
22、 i,aM=23,15,50,3,21,20,35;int i,aM=23,15,50,3,21,20,35;int bM;int bM; for(i=0;iM;i+) bi=ai; for(i=0;iM;i+) bi=ai;printf(printf(“output these numbers:noutput these numbers:n”););for(i=0;iM;i+)for(i=0;iM;i+)printf(printf(“%dn%dn”,bi);,bi);printf(printf(“nn”,),) 例例8-128-12将数组将数组a a的数据复制到数组的数据复制到数组b b中并
23、输出。中并输出。#define M 7#define M 7Void main( )Void main( )int i,aM=23,15,50,3,21,20,35;int i,aM=23,15,50,3,21,20,35;int bM;int bM;int *p=a,*q=b;int *p=a,*q=b; for(i=0;iM;i+) for(i=0;iM;i+) *q=*p;q+;p+;*q=*p;q+;p+;printf(printf(“output these numbers:noutput these numbers:n”););for(i=0;iM;i+)for(i=0;iM;i+
24、)printf(printf(“%dn%dn”,bi);,bi);Printf(Printf(“nn”,),) 例例8-128-12将数组将数组a a的数据复制到数组的数据复制到数组b b中并输出。中并输出。#define M 7#define M 7void main( )void main( )int i,aM=23,15,50,3,21,20,35;int i,aM=23,15,50,3,21,20,35;int bM;int bM;int *p=a,*q=b;int *p=a,*q=b; for(i=0;iM;i+) for(i=0;iM;i+) *q+=*p+;*q+=*p+;pri
25、ntf(printf(“output these numbers:noutput these numbers:n”););for(i=0;iM;i+)for(i=0;iM;i+)printf(printf(“%dn%dn”,bi);,bi);printf(printf(“nn”,),) printf(“%d”,*q+);8.3.3 数组名作为函数参数数组名作为函数参数,实参和形参可归纳为以下四种情况实参和形参都用数组名int f(int x,int n) void main()int array10;f(array,10);实参用数组名,形参用指针变量int f(int *x,int n) v
26、oid main()int array10;f(array,10);实参用指针变量,形参用数组名int f(int x,int n) void main()int array10,*p=array;f(p,10);实参和形参都用指针变量int f(int *x,int n) void main()int array10,*p=array;f(p,10);说明:说明:数组元素作函数参数,与一般变量相同,是数组元素作函数参数,与一般变量相同,是“单单向值传递向值传递”数组名作函数参数,是数组名作函数参数,是“单向地址传递单向地址传递单向地址传递单向地址传递”即实参数组与形参数组对应内存中同一个数组
27、,即实参数组与形参数组对应内存中同一个数组,调用时实参将数组首地址传给形参。调用时实参将数组首地址传给形参。 数组名及指向数组的指针变量作函数参数,其作数组名及指向数组的指针变量作函数参数,其作用是一样的。用是一样的。数组名是可以即用的,而指针变量必须赋值后才数组名是可以即用的,而指针变量必须赋值后才能使用。能使用。实参与形参有实参与形参有4种对应关系。种对应关系。例如例例8-14用选择法对用选择法对10个整数按从大到小排序(用指针法)个整数按从大到小排序(用指针法)#include #include void sort(int *p,int n)void sort(int *p,int n)
28、 int i, j, k, t;int i, j, k, t; for(i=0;in-1;i+) for(i=0;in-1;i+) k=i; k=i; for(j=i+1;jn;j+) for(j=i+1;j*(p+k) k=j; if(*(p+j)*(p+k) k=j; if(k!=i) if(k!=i) t=*(p+i); t=*(p+i); *(p+i)=*(p+k); *(p+i)=*(p+k); *(p+k)=t; *(p+k)=t; void main()void main() int *p, i, a10;int *p, i, a10; p=a; p=a; for(i=0;i10
29、;i+) for(i=0;i10;i+) scanf(%d,p+);scanf(%d,p+); p=a; p=a; sort(p,10); sort(p,10); for(p=a,i=0;i10;i+) for(p=a,i=0;i10;i+) printf(%5d,*p); printf(%5d,*p); p+; p+; 【例例8-15】将数组将数组a中前中前n个元素按相反顺序存放。个元素按相反顺序存放。 #include void inv(int *x,int n )int *i,*j,temp;for(i=x,j=x+n-1;ij;i+,j-)temp=*i;*i=*j;*j=temp;v
30、oid main() int i,n,a10=2,4,6,8,10,12,14,16,18,20;int *p;printf(the original array:n);for(i=0;i10;i+)printf(%d,ai);printf(n);p=a; /*给实参指针变量p赋值*/printf(input to n:n);scanf(%d,&n);inv(p,n); /*实参p为指针变量*/printf(the array after invented:n);for(p=a;pa+10;p+)printf(%d,*p);printf(n);8.3.4 指向多维数组的指针和指针变量1.多维数
31、组的地址以二维数组为例,说明多维数组的地址: int s34=1,3,5,7,2,4,6,8,9,1,0,1;1 3 5 72 4 6 89 1 0 1s0s1s2s135724689101s0s1s2s此二维数组可以看作三个一维数组s为二维数组的首地址s0或*s为第一个一维数组的首地址s00或*(*s+0)为第一个一维数组的第一个元素某行地址某元素地址某元素值s(二维数组名,数组首地址,0行首地址)s+0;s0;&s0(第0行首地址)&s00;s0+0;*(s+0)(第0行第0列)s00;*(s0+0);*(*(s+0)(第0行第0列元素值)s+1;s1;&s1(第1行首地址)&s10;s1
32、+0;*(s+1)(第1行第0列)s10;*(s1+0);*(*(s+1)(第1行第0列元素值)s+2;s2;&s2(第2行首地址)&s20;s2+0;*(s+2)(第2行第0列)s20;*(s2+0);*(*(s+2)(第0行第0列元素值)s+i;si;&si(第2行首地址)&sij;si+j;*(s+i)+j(第i行第j列)sij;*(si+j);*(*(s+i)(第0行第0列元素值)1.行转列的概念表8-1 二维数组的指针表示形式表示形式含义地址s二维数组名,数组首地址,0行首地址2000s0,*(s+0),*s第0行第0列元素地址2000s+1,&s1第1行首地址2008s1,*(s+
33、1)第1行第0列元素地址2008s1+2,*(s+1)+2,&s12第1行第2列元素地址2012*(s1+2),*(*(s+1)+2),s12第1行第2列元素的值数值5试分析下面程序,以加深对多维数组地址的理解。 #include #include void main()int s34= 0,2,4,6,1,3,5,7,9,10,11,12;printf(%#x,%#xn,s,*s);printf(%#x,%#xn,s0,*(s+0);printf(%#x,%#xn,&s0,(s+0);printf(%#x,%#xn,s1,*(s+1);printf(%#x,%#xn,&s10,*(s+1)+
34、0);printf(%#x,%#xn,s2,*(s+2);printf(%d,%dn,s10,*(*(s+1)+0);2. 指向多维数组的指针变量(1)指向数组元素的指针变量:例8-16#include void main() int a34=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); 说明:说明:若要输出某个指定的数组元素,如a12,用指针如何实现,则必须计算出该元素在数组中的相对位置。计算aij在数组中的相对位移量的公式为:i
35、*m+j,如a12的相对位移量为:1*4+2=6,用指针则p+6即为a12的地址。(2)指向由指向由m个数组成的一维数组的指针变量个数组成的一维数组的指针变量int a34; int (*p)4;p=a;1 3 5 72 4 6 89 1 0 1p+1pP为指针变量名为指针变量名例例8-17 输出二维数组任一行任一列元素的值输出二维数组任一行任一列元素的值#include void main()int a34=1,3,5,7,9,11,13,15,17,19,21,23; int (*p)4; int i,j;p=a; scanf (i=%d,j=%d,&i,&j); printf (a%d,
36、%d=%dn,i,j,*(*(p+i)+j); 说明:p+2和*(p+2)具有相同的值, (p+2)+3 和*(p+2)+3的值就不同了。3.多维数组的指针作函数参数多维数组的指针作函数参数 例8-18有一个班,3个学生,各学4门课,计算总平均分数,及第n个学生的成绩#include void main() void ave(float *p,int m);void search(float (*p)4 ,int n);float score34=65,66,67,68,78,79,80,81,66,67,68,69;int n;ave(*score,12);printf(enter a nu
37、mber to n:n);scanf(%d,&n);search(score,n);void ave(float *p,int m) float *end=p+m;float aver=0;for(;pend;p+)aver=aver+*p;aver=aver/m;printf(Average=%6.2fn,aver);void search(float (*p)4 ,int o) int i; for(i=0;i4;i+) printf(%6.2f,*(*(p+o)+i);8.4指针与字符串1.字符数组将字符串的各字符(包括结尾标志0)依次存放到字符数组中,利用下标变量或数组名对数组进行操作
38、。【例8-19】 字符数组应用#include void main()char str=I am a boy.;printf(%sn,str);运行结果I am a boy.程序说明程序说明字符数组str长度为空,默认的长度是字符串中字符个数外加结尾标志,如上例str数组长度应该为12。str是数组名,它表示字符数组首地址,str+3表示序号为3的元素的地址,它指向m。str 3,*(str+3)表示数组中序号为 3的元素的值(m)。字符数组允许用%s格式进行整体输出。2.2.字符指针字符指针对字符串而言,也可以不定义字符数组,直接定义指向字符串的指针变量,利用该指针变量对字符串进行操作。【例
39、例8-20】字符指字符指针应针应用用#include void main()char *str=I am a teacher.;printf(%sn,str);例例8-21 输入两个字符串输入两个字符串,比较是否相等比较是否相等,相等输出相等输出YES,不等输出不等输出NO.#include stdio.h#include string.hvoid main( )int t=0;char *s1,*s2;char str120,str220;s1=str1;s2=str2;gets(s1);gets(s2);while(*s1!=0&*s2!=0)if(*s1!=*s2) t=1;break;
40、s1+;s2+;if(t=0) printf(YES);else printf(NO);(1) 用字符数组作函数参数。例用字符数组作函数参数。例8-23复制字符串复制字符串#include stdio.hvoid copy_string(char from, char to) int i=0;while(fromi!=0) toi=fromi;i+;toi=0; void main()char a=I am a teacher.; char b=you are a student.; printf (stirng a=%snstring b =%sn,a,b); copy_string(a,b
41、);printf (stirng a=%snstring b =%sn,a,b);8.4.2字符串指针作函数参数字符串指针作函数参数void main()char str1=I am a teacher.; char str2=you are a student.,*a=str1,*b=str2; printf (stirng a=%snstring b =%sn,a,b); copy_string(a,b); printf (stirng a=%snstring b =%sn,a,b);(2)形参用字符指针变量形参用字符指针变量#include void copy_string(char *
42、from, char *to) for (;*from !=0;from+,to+) *to=*from; *to=0;void main()char str1=I am a teacher.; char str2=you are a student.,*a=str1,*b=str2; printf (stirng a=%snstring b =%sn,a,b); copy_string(a,b); printf (stirng a=%snstring b =%sn,a,b);例8-22 写一函数判断一个字符串是否为回文。(顺读与逆读相同)算法:1、令q指向最后一个字符2、若*p=*q,则两指
43、针向里靠拢,直到p=q,则return 1,否则,return 0;int ishuiwen(char *p)int ishuiwen(char *p)char *q=p; char *q=p;while (*q!=0)q+; while (*q)q+; q-;q-;while(pq)while(pq)if(*p=*q)p+;q-;if(*p+!=*q-)else return 0;return 0;return 1; return 1;【例例8-23】将输入字符串中的大写字母改成小写字母,将输入字符串中的大写字母改成小写字母,然后输出字符串。然后输出字符串。 #include stdio.h
44、#include string.hvoid inv(char *s)int i;for(i=0;i=A & *(s+i)=Z)*(s+i)+=32;void main()char str10,*string=str;gets(string);inv(string);puts(string);因为字符串是一个整体,故只要指出字符串在内存中的首地址,无论采用数组名或指针变量,均可以访问字符串的全部成员,直到遇“0”为止。str1或*(str+1)均表示第1个字符数值型数组只能逐个元素引用,不能企图用数组名来输出全部元素。 字符串可以全部引用(用%s格式),也可以访问每一个元素(用%c格式)。设一个
45、指针变量,通过改变它的值来指向不同的字符串。说明:8.4.3字符指针变量与字符数组的比较字符指针变量与字符数组的比较存储的内容不同:字符数组可以存字符串,存的是字符;字符指针变量存的是字符串在内存的首地址。赋值方式不同字符数组只能对各个元素赋值;字符指针变量只赋值一次,赋的是地址。如:char a10,*p; p=“china”; a=“hello”当没有赋值时: 字符数组名代表了一个确定的地址;字符指针变量中的地址是不确定的。如:char a10,*p; scanf(“%s”,a) scanf(“%s”,p)字符数组名不是变量,不能改变值; 字符指针变量可以改变值。如:a+; p+;可以象数
46、组那样用下标形式引用指针变量所指字符串的字符。如:char *p=“abcd”;putchar(p3);p2=x;用指针变量指向一个格式字符串;char *format;format=“a=%d,b=%fn”;printf(format,a,b);也可以用字符数组实现。如:char format=“a=%d,b=%fn”;printf(format,a,b);但不能:char format; format=“a=%d,b=%fn”; printf(format,a,b);8.5 指针和函数8.5.1 函数的指针一个函数在调用时被分配一个入口地址,即函数指针,可以定义一个指向函数的指针变量来指向
47、它。一、定义指向函数的指针变量基类型 (*指针变量名)(); 例如:int (*p)( )为一个指向函数的指针变量;二、将指针变量指向某函数指针变量名=函数名;三、利用指向函数的指针变量调用函数(*指针变量名)(实参表)例说明:(1)定义的形式:数据类型(*指针变量名)();(2) 函数的调用可以通过函数名调用,也可以通过函数指针调用。(3) (*p)()表示定义一个指向函数的指针变量,它并不固定指向哪一个函数的。(4) 给函数指针变量赋值时,只需给出函数名而不必给出参数。p=max;(5) 用指针变量调用函数时,只需将(*p)代替函数名。c=(*p)(a,b);(6) p+n, p+, p-
48、无意义8.5.2 用指向函数的指针变量作函数参数指向函数的指针是很有用的,理由有2:第一、我们不可能把函数本身当成参数传给另一个函数,但可以把指针当作参数。第二、我们不可能把函数本身存入数组或结构体中,却可以把函数指针存入数组或结构体中。用函数指针可以设计所谓的派遣(dispatch)表,有一个index变量1,2.5,如index为1时执行fn1,其余类推。要实现这一功能,通常要一大堆if或switch语句测试index的值。用指向函数的指针可使程序大为简化。int (*fn0)(),(*fn1)(),(*fn2)(),(*fn3)(),(*fn4)(),(*fn5)(), static i
49、nt (*disptach)()= fn0,fn1,fn2,fn3,fn4,fn5 . (*disptachindex)();【例例8.248.24】编编制制函函数数funcfunc,在在调调用用它它的的时时候候,每每次次实实现现不不同同的的功功能能。对对于于给给定定的的两两个个数数a a和和b b,第第一一次次调调用用funcfunc时时找找到到a a和和b b中中的的大大数数;第第二二次次调调用用processprocess时时找找到到x x和和y y中中的的小小数数;第第三三次次调调用用funcfunc时返回时返回a a和和b b的和。的和。#include #include int m
50、ax(int,int);int max(int,int);int min(int,int);int min(int,int);int add(int,int);int add(int,int);void func(int a,int b,int (*fun)(int,int);void func(int a,int b,int (*fun)(int,int);void main() void main() int x,y;int x,y;printf(Enter two number to a and b:);printf(Enter two number to a and b:);scanf
51、(%d,%d,&x,&y);scanf(%d,%d,&x,&y);printf(max=);printf(max=);func (x,y,max);func (x,y,max);printf(min=);printf(min=);func (x,y,min);func (x,y,min);printf(sum=);printf(sum=);func (x,y,add);func (x,y,add); max(int a,int b) max(int a,int b) int c;int c;c=(ab)?a:b;c=(ab)?a:b;return(c);return(c); min(int a
52、,int b) min(int a,int b) int z;int z;z=(ab)?a:b;z=(ab)?a:b;return(z);return(z); add(int a,int b) add(int a,int b) int c;int c;c=a+b;c=a+b;return(c);return(c); /*/*函数定义,参数函数定义,参数funfun是指向函数的指针,该函数有两个整型形式,函数类型是指向函数的指针,该函数有两个整型形式,函数类型是整型是整型* */ / void func(int a,int b, int (*fun)(int,int) void func(int
53、 a,int b, int (*fun)(int,int) int result;int result;result=(*fun)(a,b);result=(*fun)(a,b);printf(%dn,result);printf(%dn,result); 8.5.3返回指针值的函数类型名函数名(参数名)int *a(x,y); 表示一个返回指向整型变量的指针的函数【例8.25】以下函数把两个整数形参中较大的那个数的地址作为函数值传回。#include void main()int *maxc(int,int);/*函数说明*/ int *p,i,j; printf(Enter two num
54、ber to i,j:); scanf(%d,%d,&i,&j); p=maxc(i,j);/*调用函数fun,返回最大数的地址赋值指针变量p*/ printf(max=%d,*p);int *maxc(int x,int y)/* 定义返回值为整型指针的函数maxc */int *z; if(xy) z=&x; else z=&y; return(z);8.6.1指向指针的指针指向指针的指针:一个变量中存放的是一个指针变量的地址。#include void main()int i=2;int *p1;p1=&i ; int *p2;p2=&p1;printf(%dn,i);printf(%#
55、xn,p1);printf(%#xn,p2); printf(%dn,*p1);printf(%dn,*p2);8.6 指向指针的指针8.6.2 指针数组类型名数组名数组长度一个数组,其元素均为指针类型数据.例如: int * name4 ;试比较:int a4;它适合于用来指向若干个字符串,使字符串处理更方便;比用字符数组节省空间;指针数组的元素也可以指向整型或实型数据例8.26 #include void main()int a5=1,3,5,7,9;int *num5=&a0,&a1,&a2,&a3,&a4;int *p,i;p=num; for(i=0;i5;i+) printf (%
56、dt, *p); p+;Follow meBASICGreat WallFORTRANComputer designname0 name1 name2 name3 name41000p20002010201620272035printf(%#xt,name);printf(%#xt,*name);printf(%ct,*name); printf(%#xt,name2);printf(%st,name2);printf(%ct,*(name2+6);p=name+2;printf(%#xt,*p);printf(%st,*p);printf(%ct,*(*p+6);printf(n);指针的指
57、针#include void main()char *name5,*p;char str520=Follow me,BASIC,Great Wall,FORTRAN,Computer design;int i;for(i=0;i5;i+)namei=stri;printf(%#xt,name);printf(%#xt,*name);printf(%ct,*name); printf(%#xt,name2);printf(%st,name2);printf(%ct,*(name2+6);p=name+2;printf(%#xt,*p);printf(%st,*p);printf(%ct,*(*p
58、+6);printf(n);【例8.27】指针数组的应用#include void main() char *name=C Program,BASIC,Computer,English,Word;char *p;for(p=name;pname+4;p+)printf(%sn,*p);运行结果:C Program BASICComputer EnglishWord例8.28 将若干字符串按字母(由小到大)顺序输出#include #include void main()void sort(char *name,int n); void print (char *name,int n);char
59、 *name=follow, basic, great wall, fortran, computer design;int n=5;sort(name,n);print (name,n);void print (char *name,int n) int i; for(i=0;in;i+) printf(%sn,namei);void sort (char *name ,int n)char *temp;int i,j,k;for (i=0;in-1;i+) k=i; for(j=i+1; j0) k=j; if (k!=i) temp=namei;namei=namek;namek=tem
60、p; 8.6.3 指针数组作main函数的形参例如:main (int argc,char * argv)由于main函数是由系统调用的,故形参值应由系统提供,即实参是和命令一起给出的。命令名 参数1 参数2 参数3 .比如: file1 China Beijing Baoding argc: 命令行参数的个数(包括命令名),本例 argc 为 4argv:为指针数组,它指向命令行中的字符串B a o d i n g 0f i l e 1 0B e i j i n j 0C h i n a 0#include void main (int argc,char *argv)while (argc
61、1)+argv; printf (%sn, *argv); -argc; File1 China Beijing China Beijing 作业:1、编一程序,首先将一个包含10个数的数组按照升序排列,然后将从一指定位置m开始的n个数按照逆置后重新排列,并将新生成的数组输出。要求使用指针控制方法实现上述功能。2、选修某课程的学生有5人,学生的信息包括学号、姓名和成绩,按成绩高低对学生排序,输出排序后的学生信息。从键盘输入一学生姓名,查出其成绩和成绩等级。(用指向指针的指针处理学生的姓名、学号)第第8章结束章结束&a&a&b&b95bapoint2point1p2p1&a&a&b&b59bap
62、oint2point1p2p1例例. 8-8输入两个整数输入两个整数按大小顺序输出按大小顺序输出swap(int *p1,int *p2)int p ;p=*p1 ;*p1=*p2 ;*p2=p ;main()int a,b ;int *point1,*point2;scanf(“%d,%d”,&a,&b);point1=&a;point2=&b;if (ab) swap(point1,point2);printf(“n%d,%d”,a,b) ;swap(int *p1,int *p2)int *temp ;*temp=*p1 ;*p1=*p2 ;*p2=*temp ;swap(int x,i
63、nt y) int temp ;temp=x ;x=y ;y=temp ;swap(a,b);结果:结果:5,99,5此时temp无确定的指向 int *temp,x;temp=&x;6556&a&a&b&b95bapoint2point1p2p1&b&a&a&b95bapoint2point1p2p1不能企图通过改变指针形参不能企图通过改变指针形参的值而使指针实参的值改变的值而使指针实参的值改变swap(int *p1,int *p2)int *p ;p=p1 ; p1=p2 ;p2=p ;main()int a,b ;int *point1,*point2;scanf(“%d,%d”,&a
64、,&b);point1=&a;point2=&b;if (ab) swap(point1,point2);printf(“n%d,%d”,a,b) ;例8-13编写一函数求一维数组的最大元素及下标位置(要求使用指针)已知:数组首地址p,元素个数n;结果:下标k#include int max_array(int *p,int n)int k=0,max=*p,i;for(i=0;imax)max=*(p+i);k=i;return k;void main( )int a10=23,43,52,23,5,22,33,35,96,34;int i,*p=a,k;for(i=0;i10;i+)pri
65、ntf(%5d,*(p+i);k=max_array(a,10);printf(nmax=a%d=%dn,k,*(p+k); 一般函数调用方法一般函数调用方法#include #include void main()void main() int max(int *p); int max(int *p);int i,m,a10;int i,m,a10;for(i=0;i10;i+)for(i=0;i10;i+)scanf(%d,&ai);scanf(%d,&ai);m=max(a);m=max(a);printf(max=%d,m);printf(max=%d,m); max(int *p)m
66、ax(int *p) int i,t=*p;int i,t=*p;for(i=1;i10;i+)for(i=1;it) t=*(p+i);if(*(p+i)t) t=*(p+i);return (t);return (t);定义指向函数的指针变量调定义指向函数的指针变量调用函数的方法用函数的方法void main()void main()int max(int *p);int max(int *p);int i,m,a10;int i,m,a10; int (*f)(int *p); int (*f)(int *p); for(i=0;i10;i+) for(i=0;i10;i+) scanf
67、(%d,&ai); scanf(%d,&ai); f=max; m=(*f)(a); f=max; m=(*f)(a); printf(max=%d,m);printf(max=%d,m);int max(int *p)int max(int *p)int i,t=*p;int i,t=*p; for(i=1;i10;i+) for(i=1;it) t=*(p+i); if(*(p+i)t) t=*(p+i);return (t);return (t);*p+ 的使用 #include void main() int a5=2,3,4,5,6; int *p=a,c; c=*p+; print
68、f(%d,%dn,c, *p); 结果:结果:3,3#include void main()int a5=2,3,4,5,6; int *p=a,c; c=*(+p); printf(%d,%dn,c, *p); 结果:结果:2,3例例8-9输入输入a、b、c 3个整数,按大小顺序输出个整数,按大小顺序输出swap(int *pt1,int *pt2) int temp; temp=*pt1;*pt1=*pt2;*pt2=temp;exchange (int *q1,int *q2,int *q3)if (*q1*q2) swap(q1,q2);if (*q1*q3) swap(q1, q3)
69、;if (*q2*q3) swap(q2, q3);void main() int a,b,c,*p1,*p2,*p3;scanf(%d,%d,%d,&a,&b,&c);p1=&a,p2=&b;p3=&c;exchange(p1,p2,p3);printf (n%d,%d,%dn,a,b,c);运行结果:9,0,1010,9,0例8.7 将数组a中n个整数按相反的顺序存放void inv(int x , int n) int temp,i,j,m=(n-1)/2;for(i=0;i=m;i+) j=n-1-i; temp=xi;xi=xj;xj=temp;return;main () int
70、i, a10=3,7,9,11,0, 6,7,5,4,2;printf( the orginal array:n);for(i=0;i10;i+) printf (%d, ,ai);printf(n);inv(a,10);printf (the array has been inverted:n);for(i=0;i10;i+) printf (%d, ,ai);printf(n);形参不用数组,该用改用指针变量void inv(int *x, int n) int *p,temp,*i,* j, m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i+,j-) temp
71、=*i; *i=*j;*j=temp;return;main () int i, a10=3,7,9,11,0, 6,7,5,4,2;printf( the orginal array:n);for(i=0;i10;i+) printf (%d, ,ai);printf(n);inv(a,10);printf (the array has been inverted:n);for(i=0;i10;i+) printf (%d, ,ai);printf(n);8.8 从10个数中找出其中最大值和最小值int max,min;void max_min_value(int array ,int n)
72、int *p,*array_end;array_end=array+n;max=min=*array;for(p=array+1;pmax) max=*p;else if(*pmin)min=*p;return;main () int i, number10=-2,4,6,8,0, -3,45,67,89,100;printf( the 10 number :n);for(i=0;i10;i+) printf (%d, ,numberi);printf(n);max_min_value(number,10);printf(nmax=%d,min=%d:n,max,min);实参用指针变量int
73、 max,min;void max_min_value(int array ,int n)int *p,*array_end;array_end=array+n;max=min=*array;for(p=array+1;pmax) max=*p;else if(*pmin)min=*p;return;main () int i, number10=-2,4,6,8,0, -3,45,67,89,100,*p; p=number;printf( the orginal array:n);for(i=0;i10;i+,p+) printf (%d, ,*p);printf(n); p=number
74、;max_min_value(p,10);printf(nmax=%d,min=%d:n,max,min);例8.9 用实参指针变量改写例8.7void inv(int *x, int n) int *p,temp,*i,* j, m=(n-1)/2;i=x;j=x+n-1;p=x+m;for(;i=p;i+,j+) j=n-1-i; temp=*i; *i=*j;*j=temp;return;main () int i, arr10,*p=arr;printf( the orginal array:n);for(i=0;i10;i+,p+) scanf (%d ,p); p=arr;prin
75、tf(n);inv(p,10);printf (the array has been inverted:n);for(p=arr;parr+10;p+) printf (%d, ,*p);printf(n);8.10 用选择法对10个整型数组排序main()int i,*p,a10;p=a;for(i=0;i10;i+)scanf(%d,p+);p=a;sort(p,10);for(p=a,i=0;i10;i+)printf(%d ,*p+);sort(int x,int n) int i,j,k,t;for(i=0;in-1;i+)k=i; for(j=i+1;jxk) k=j; if(k!=1) t=xk;xk=xi;xi=t;