版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第十章第十章 指针指针 指针指针: :c c的一个的一个重要概念重要概念、重要特色重要特色。它使。它使c c具备了强大的功能,使具备了强大的功能,使c c成为程序设计语言之首。成为程序设计语言之首。正确而灵活地运用它,就可以方便地处理很多正确而灵活地运用它,就可以方便地处理很多其它高级语言所不能处理的问题。其它高级语言所不能处理的问题。 不掌握不掌握指针指针等于没有掌握等于没有掌握c c语言的语言的精华精华。 10 101 1 指针的概念指针的概念 简单地说,简单地说,指针就是地址指针就是地址。 要掌握指针的概念就必须弄清:要掌握指针的概念就必须弄清: 内存地址概念内存地址概念? ? 变量与地
2、址的关系变量与地址的关系? ? 如何通过地址进行变量的存取如何通过地址进行变量的存取? ?说明例:说明例: 内存用户数据 1000 3 i 1002 6 j 1004 9 k对变量值的存取总是按地址进行的-直接访问。int i,j,k;i=3; j=6;k=i+j;程序经编译后程序经编译后,变量名就不,变量名就不复存在,以地复存在,以地址对应。址对应。也可以采用也可以采用“间接访问间接访问”方式:方式: 先将变量先将变量i i的地址存放到另一变量的地址存放到另一变量p1p1中,中,要访问要访问i i时,先取出时,先取出p1p1的内容(变量的内容(变量i i的地址),的地址),再去访问该地址所对
3、应的内存单元中的内容再去访问该地址所对应的内存单元中的内容(变量(变量i i的值)。的值)。 内存用户数据 1000 3 i 1002 6 j 1004 9 k 2000 1000 p1 2004 1002 p2int i,j,k;i=3; j=6;k=i+j;int *p1, *p2;p1=&i;p2=&j;在以上概念的基础上对指针下定义:在以上概念的基础上对指针下定义: 变量的地址就是该变量的变量的地址就是该变量的指针指针。 存放地址的变量称存放地址的变量称指针变量指针变量。 若若p1p1存放了变量存放了变量i i的地址,的地址, 则称则称p1p1是是指向变量指向变量i i
4、的指针变量的指针变量。10001002100410001002ijkp1p2369int i,j,k;i=3; j=6;k=i+j;int *p1, *p2;p1=&i;p2=&j; 10 102 2 变量的指针和指向变量的指针变量变量的指针和指向变量的指针变量 变量的指针变量的指针 指针变量指针变量 指向变量的指针变量指向变量的指针变量 用用“* *”代表代表“指向指向” 如如* *p1p1代表它所指向的变量代表它所指向的变量i i,同一内存单元。,同一内存单元。 以下两个语句等价:以下两个语句等价: i=3; i=3; 直接访问直接访问 * *p1=3; p1=3; 间接访
5、问间接访问int i,int i,* *p1;p1;p1=&i;p1=&i; 内存用户数据 1000 3 i 1002 6 j 1004 9 k 2002 1000 p1 2004 1002 p2int i,j,k;i=3; j=6;k=i+j;int *p1, *p2;p1=&i;p2=&j;*p1=5;*p2=8;58 指针变量的定义指针变量的定义 指针变量也必须先定义后使用。指针变量也必须先定义后使用。 int int * *p1;p1;注意:注意: * *表示该变量为指针变量,但变量名是表示该变量为指针变量,但变量名是p1p1。 一个指针变量只能指向同一
6、类型的变量。一个指针变量只能指向同一类型的变量。 int i,int i,* *p1;p1; float a; float a; p1=&i; p1=&i; 合法合法 p1=&a; p1=&a; 不合法不合法 指针变量的引用指针变量的引用 两种用法:两种用法: 用地址运算符用地址运算符& & p1=&i p1=&i; 用指针运算符用指针运算符* * (实行间接访问)(实行间接访问) * *p1=100; k=p1=100; k=* *p1;p1; 注意:注意: 指针变量只能放地址(指针)。指针变量只能放地址(指针)。 p1=100
7、; p1=100; 不允许不允许 使用指针运算符使用指针运算符* *之前,之前,p1p1必须被赋值(即必须被赋值(即p1p1必必须存放了某个变量的地址)须存放了某个变量的地址)例:例: t10-1.c 注意:要区别定义和引用中的“*”main() int a=100,b=10; int *p1,*p2; 定义指针变量,尚无体定义指针变量,尚无体指向指向 p1=&a; p1p1指向指向a a p2=&b; p2p2指向指向b b printf(“*p1=%d, *p2=%d n”, *p1, *p2); printf(“&a=%x,& b=%x n”,&a
8、, &b); printf(“p1=%x, p2=%x n”, p1, p2); printf(“& p1=%x, &p2=%x n”, &p1, & p2);运算结果:*p1=100, *p2=10&a=12ff7c,& b=12ff78p1=12ff7c, p2=12ff78&p1=12ff74, &p2=12ff70要特别注意以下用法的后果:要特别注意以下用法的后果:egp1.c int *p1; *p1=100;例:输入例:输入a a和和b b两个整数,按先大后小的顺序输出两个整数,按先大后小的顺序输出 main(
9、) t10-2.c int a,b,*p1, *p2, *p; scanf(“%d,%d”,&a,&b); 1000 5 a p1=&a; p2=&b; 1002 9 b if(ab) p=p1; p1=p2; p2=p; printf(“n %d,%d”,a,b); 2000 p1 printf(“n%d,%d”,*p1,*p2); 2004 p2 2006 p 改变p1和p2的指向10001002100210001000重要概念:重要概念: 只要将某一变量的地址存入指针变量中,只要将某一变量的地址存入指针变量中,就可通过指针变量间接访问该变量。就可通过指针变
10、量间接访问该变量。 配钥匙!配钥匙!swap(int p1, int p2) int t; t=p1; p1=p2; p2=t; 1000 5 a 1002 9 b main() int a,b; scanf(“%d,%d”,&a,&b); 2000 p1 if(ab)swap(a, b); 2004 p2 printf(“n %d,%d”,a,b); 2006 t t10-3-1.c59 595例 不用指针变量作函数参数,将两个整数按大小顺序输出。怎样直接修改a、b的值呢?修改原件修改原件用指针!用指针! 指针变量作为函数的参数指针变量作为函数的参数 可将指针变量作函数的参数
11、,接受实参可将指针变量作函数的参数,接受实参地址,获得具体指向,进而通过指针变量间地址,获得具体指向,进而通过指针变量间接访问主调函数的变量。接访问主调函数的变量。例t10-3.c用指针变量作函数参数,将两个整数按大小顺序输出。swap(int *p1, int *p2) int t; t=*p1; *p1=*p2; *p2=t; 1000 5 a 1002 9 b main() int a,b; scanf(“%d,%d”,&a,&b); 2000 p1 if(ab)swap(&a,&b); 2004 p2 printf(“n %d,%d”,a,b); 200
12、6 t 10001002595 重要概念:重要概念:使用指针变量作函数参数,使用指针变量作函数参数,被调函数可以将多个结果交给主调函数。被调函数可以将多个结果交给主调函数。 数组名做参数,可返回该数组所有元素数组名做参数,可返回该数组所有元素 还记得那个求成绩最高、最低和平均值还记得那个求成绩最高、最低和平均值的例子?还需要用全局变量吗?的例子?还需要用全局变量吗?例例t10-4-2.c t10-4-2.c :求:求n n个数的最大值、最小值和平均值。个数的最大值、最小值和平均值。float aver(int a, int n, int *max, int *min) int i; float
13、 s=0; *max=a0; *min=a0; for(i=0;i*max) *max=ai; if(ai*min) *min=ai; return(s/100);main() int a100,i,max,min;float av;for(i=0;i100;i+) scanf(“%d”,&ai);av=aver(a,100,&max,&min);printf(“ %d,%d,%f”,max,min,av);例例t10-4-1.c :编写函数,求一元二次方程的两个实根。:编写函数,求一元二次方程的两个实根。#include “math.h” ? root(float a
14、,float b,float c, ) float d; d=b*b-4*a*c; if(d0|a=0)return(0); ? =(-b+sqrt(d)/2/a; ? =(-b-sqrt(d)/2/a; return(1); float *x1, float *x2 *x1 *x2 int main() int k; float a,b,c,x1,x2; scanf(“%f,%f,%f”,&a,&b,&c); k=root(a,b,c,&x1,&x2); if(k) printf(“n %f,%f”,x1,x2); 输入:1, -10 ,25输出:5.
15、000000,5.000000函数参数:函数参数:如不需改变(只读):一般参数如不需改变(只读):一般参数如需改变(读写):指数参数如需改变(读写):指数参数 10 103 3 数组的指针和指向数组的指针变量数组的指针和指向数组的指针变量数组有一个首地址: 数组的指针数组的指针。每个数组元素也都有地址: 数组元素的指针数组元素的指针。532168742000200220042006 指向数组元素的指针变量指向数组元素的指针变量 int a10,*p; p=a; 指向数组指向数组 p=&a0; 指向数组元素指向数组元素 51247680392000200220042006p 通过通过指针
16、引用数组元素指针引用数组元素 int a10,*p; p=&a0; 或者或者 p=a; /p p指向指向a0a0 *p=1; 等效于等效于a0=1a0=1; ; 即可通过即可通过p p来访问来访问a0a0也可以通过也可以通过p p来访问其它元素:来访问其它元素: * *(p+1)=3; (p+1)=3; 等效于等效于a1=3;a1=3; 其中其中p+1p+1指向指向a1a1注意:注意:p+1p+1不是地址加不是地址加1 1,而是加一个数据类型单,而是加一个数据类型单位。位。一般地一般地, ,当当p p指向指向a0a0时时, ,即即p=&a0; 或者或者 p=a; p+i a+i
17、 a+i &ai &ai*(p+i) * *(a+i)(a+i) ai ai pi pi即以下几个语句等效:即以下几个语句等效:ai=10; *(p+i)=10; *(a+i)=10; pi=10;举例:用三种方法输出数组元素例t10-5-1.c 用“数组名数组名+下标下标”的方法main()int i, a5;for(i=0; i5; i+) scanf(“%d”,&ai);for(i=0; i5; i+)printf(“&a%d=%x, a%d=%d n”, i,&ai, i, ai );输入: 55 66 77 88 99 输出: &a0=
18、ffce, a0=55 &a1=ffd0, a1=66 &a2=ffd2, a2=77 &a3=ffd4, a3=88 &a4=ffd6, a4=99 ffcc 55 a0ffce 66 a1ffd0 77 a2ffd2 88 a3ffd4 99 a4ffd6 a5举例:用三种方法输出数组元素例t10-5-2.c 计算“数组名计算地址数组名计算地址”的方法main() int i, a5; for(i=0;i5;i+) scanf(“%d”,a+i); for(i=0;i5;i+)printf(“a+%d)=%x,*(a+%d)=%d n”,i,(a+i), i
19、,*(a+i);输出: (a+0)=ffcc, *(a+0)=55 (a+1)=ffce, *(a+1)=66 (a+2)=ffd0, *(a+2)=77 (a+3)=ffd2, *(a+3)=88 (a+4)=ffd4, *(a+4)=99 ffcc 55 a0ffce 66 a1ffd0 77 a2ffd2 88 a3ffd4 99 a4ffd6 a5举例:用三种方法输出数组元素例t10-5-3_new.c 用“指针变量指针变量+下标下标”的方法(指针法指针法i )main()int *p, a5,i; p=a;for(i=0;i5;i+) scanf(“%d”,p+i);for(i=0;
20、i5;i+)printf(&p%d=%x, p%d=%d, *(p+%d)=%dn,i,&pi,i,pi,i,*(p+i);12ff6c 55 p012ff70 66 p112ff74 77 p212ff78 88 p312ff7c 99 p4输出:&p0=12ff6c, p0=55, *(p+0)=55&p1=12ff70, p1=66, *(p+1)=66&p2=12ff74, p2=77, *(p+2)=77&p3=12ff78, p3=88, *(p+3)=88&p4=12ff7c, p4=99, *(p+4)=99举例:用三种方
21、法输出数组元素(例t10-5-4_new.c )用“指针变量指向数组元素指针变量指向数组元素”法(指针法指针法ii)main()int *p, a5; for(p=a; p (a+5); p+)scanf(“%d”,p+i); for(p=a; p (a+5); p+)printf(“p=%x, *p=%d n”, p,*p);输出:p=12ff6c,*p=55p=12ff70,*p=66p=12ff74,*p=77p=12ff78,*p=88p=12ff7c,*p=9912ff6c 55 a012ff70 66 a112ff74 77 a212ff78 88 a312ff7c 99 a4p+
22、: 合法, 因p是指针变量,而变量可以用 +运算符的a+: 不合法, 因为a是数组名,其值是数组元素的首地址,分配之后不可变。举例:用三种方法输出数组元素(例t10-5-4.c )指针变量当作数组名使用(混合指针法) main() int a5,*p=a,i; for(p=a;pa+5;p+) scanf(“%d”,p); p=a;/不能漏!不能漏! for(i=0;i5;i+) printf(“&p%d=%x,p%d=%d,*(p+%d)=%dn”, i,&pi, i,pi,i,*(p+i); 输出:&p0=12ff6c,p0=55,*(p+0)=55&p1=
23、12ff70,p1=66,*(p+1)=66&p2=12ff74,p2=77,*(p+2)=77&p3=12ff78,p3=88,*(p+3)=88&p4=12ff7c,p4=99,*(p+4)=9912ff6c 55 p12ff70 66 p+112ff74 77 p+212ff78 88 p+312ff7c 99 p+4通过通过指针引用数组元素的方法小结指针引用数组元素的方法小结例:累加求和的各种用法:例:累加求和的各种用法:int *p,a10;s=0;p=a;for(i=0;i10;i+)s+=ai;for(i=0;i10;i+)s+=*(a+i);for(i=
24、0;i10;i+)s+=*(p+i);for(i=0;i10;i+)s+=pi;for(i=0;i10;i+)s+=*p+; for(p=a;pa+10;p+)s+=*p; 最后一种用法效率高。数组元素地址法数组元素地址法指针法指针法i指针变量指向数组元素指针法ii指针变量当作数组名注意不能注意不能使用a+指针变量使用时的几个问题,指针变量使用时的几个问题, 若若p当前指向当前指向a数组的第数组的第i个元素,则:个元素,则:10-plus.c *p:是取出是取出ai的值的值. p + :指针指向指针指向ai+1. *p+ :等价于等价于*(p+)及及ai+ ,优先级同为,优先级同为2,从右向左
25、结合从右向左结合,将将 ai 的值取出的值取出, 后再使后再使 p增增1(不是单纯的加一,是不是单纯的加一,是p指向指向ai+1). * (+p):与与a+i等价,先将等价,先将p指向指向ai+1,然后将该元素取出然后将该元素取出. (*p)+:将将p所指的数组元素所指的数组元素ai的值取出的值取出,使使ai的值增的值增1. p- :指针指向指针指向ai-1. *(p-):与与ai-等价,等价, 将将p 所指向的第所指向的第i个数组元素取出个数组元素取出,然后使然后使p指向指向i-1元素元素. *(-p):与与a- i等价,先将等价,先将p减减1指向第指向第i-1个元素个元素,然后将其取出然后
26、将其取出. (*p)-:将将p所指的数组元素所指的数组元素ai的值取出的值取出,使使ai的值减的值减1.数组名作为函数参数数组名作为函数参数 有了指针概念的基础上,重新回顾数组名作有了指针概念的基础上,重新回顾数组名作为函数参数时,数据的传递情况:为函数参数时,数据的传递情况:void sort(void sort(int aint a, int n), int n)void sort(void sort(int int * *a a, int n), int n) 例:例:选择法排序函数选择法排序函数 void sort(int *a, int n)例t10-7-1.c int i,j,t;
27、 for(i=0;in-1;i+) for(j=i+1;jaj)t=ai; ai=aj; aj=t; 只将形参改为指针变量,仍按下标法使用只将形参改为指针变量,仍按下标法使用 void sort(int *a, int n) int i,j,t; for(i=0;in-1;i+) for(j=i+1;j*(a+j) t=*(a+i); *(a+i)= *(a+j); *(a+j)=t; 按指针法使用按指针法使用例t10-7-2.c 进一步优化:都用指针,效率更高!进一步优化:都用指针,效率更高! (例t10-7-3.c )void sort(int *a, int n) int *i, *j,
28、t; for(i=a;ia+n-1;i+) for(j=i+1;j*j) t=*i; *i=*j; *j=t; main() int a10,j; for(j=0;j10;j+)scanf(“%d”,a+j); sort(a,10); for(j=0;j10;j+)printf(“%5d”,aj); 分段排序?分段排序?例t10-7-4.c main() int a10,j; for(j=0;j10;j+)scanf(“%d”,a+j); for(j=0;j10;j+)printf(“%5d”,aj); sort(a,5);sort(a+5,5);void sort(int *a, int n
29、) int *i, *j,t; for(i=a;ia+n-1;i+) for(j=i+1;j*j) t=*i; *i=*j; *j=t; 指向多维数组的指针和指针变量指向多维数组的指针和指针变量 从本质上说,多维数组的指针与一维数组从本质上说,多维数组的指针与一维数组的指针相同,但在概念上和使用上,多维数组的指针相同,但在概念上和使用上,多维数组的指针要复杂些。的指针要复杂些。 以二维数组的指针为例:以二维数组的指针为例:二维数组的地址 :一维:a,&ai,a+i 二维:aa+i (行指针:指向第i行)ai *(a+i) (特殊的一维数组,列指针,指向行中的列)ai+j *(a+i)+
30、j &aij int a34 1357911131517192123100010081016a+0a+1a+2a0讨论以下用法的效果:讨论以下用法的效果:t10-8-1.cfor(i=0;i3;i+) scanf(“%d”,a+i);输入数据:输入数据:1 2 3讨论以下用法的效果:讨论以下用法的效果:t10-8-2.cfor(i=0;i3;i+) scanf(“%d”,a1+i);输入数据:输入数据:1 2 3讨论以下用法的效果:讨论以下用法的效果:t10-8-3.cfor(i=0;i3;i+) scanf(“%d”,a1+i+2);输入数据:输入数据:1 2 3讨论以下用法的效果:
31、讨论以下用法的效果:t10-8-4.cfor(i=0;i3;i+) scanf(“%d”,a+i+1);输入数据:输入数据:1 2 3a0+1 a0+2 a0+3一维数组与二维数组的比较一维数组与二维数组的比较第第i个个一维数组一维数组的第的第j个元个元素的地址素的地址无意义无意义*(a+i)+j第第i个个一维数组一维数组的第的第j个元个元素的值素的值无意义无意义*(*(a+i)+j)第第i个个一维数组一维数组的值的值第第i个个一维数组一维数组的首地址的首地址第第i个元素的值个元素的值*(a+i)第第i个个元素元素 的地址的地址一维数组一维数组第第i个元素的地址个元素的地址a+i二维数组的首地
32、址二维数组的首地址一维数组的首地址一维数组的首地址a二维数组二维数组一维数组一维数组注意:注意:指针运算符指针运算符*作用在行指针上的结果仍是指针作用在行指针上的结果仍是指针-列指针列指针; *作用在列指针上的结果作用在列指针上的结果-具体元素具体元素。 *(a+0),*(a+1),*(a+2) 仍是地址仍是地址。*(a+i) ai *(a0),*(a1),*(a1) 具体元素值具体元素值。*(ai)*(a+i)+j 也是地址,但要区别:也是地址,但要区别: (a+i)+j行指针行指针 (a+1)+1 ? *(a+i)+j列指针列指针 *(a+1)+1 ? 100010081016a+0a+1
33、a+2a0a1a2*(a+1)1357911131517192123 如果要通过如果要通过a+ia+i形式的地址访问数组元素的具体形式的地址访问数组元素的具体内容,则:内容,则:*(*(a+i) 或或 *(*(a+i)+j)如如:*(*(a+1) a10 *(*(a+1)+2) a12讨论:讨论:例t10-8-5.c*(a+2) *(*(a+1)+3) *(a1+1) *(*(a+1)+5)123456789111012例:求数组例:求数组a a的所有元素之和。的所有元素之和。 可有多种用法:可有多种用法:例t10-9-1.ct10-9-3.c m m行行n n列列for(i=0;im;i+)
34、 for(i=0;im;i+)for(i=0;im;i+) for(i=0;im;i+)for(j=0;jn;j+) for(j=0;jn;j+)for(j=0;jn;j+) for(j=0;jn;j+)s+=s+=aijaij; s+=; s+=* *(ai+j)(ai+j); ;for(i=0;im;i+)for(i=0;im;i+)for(j=0;jn;j+)for(j=0;jn;j+) s+= s+=* *( (* *(a+i)+j)(a+i)+j); ; aij*(ai+j)*(*(a+i)+j)指向二维数组的指针变量指向二维数组的指针变量 同样可使一个指针变量同样可使一个指针变量p
35、 p指向二维数组指向二维数组a a,再,再通过通过p p访问数组元素。访问数组元素。例t10-10.cmain()main() int a34=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; int i,k, int i,k,* *p;p; p=a; p=a; k= k=* *p;p;? ? k= k=* *(p+2);(p+2);? ? for(p=a;pa+2;p+)printf(“%3d,”, for(p=a;pa+2;p+)printf(“%3d,”,* *p); p); ? ? n列:列:aij*(p+i
36、*n+j)pi*n+j123456789101112k=p12; 不合法不合法k=*(*(p+1)+2);k=p1*4+2; 合法合法k=*(p+1*4+2);例:求矩阵的上三角元素之和。例:求矩阵的上三角元素之和。例t10-11.cmain() int a34,*p,i,j,s=0; 输入输入a p=a; for(i=0;i3;i+) for(j=i;j4;j+) s+=pi*4+j; 或或 s+=*(p+4*i+j) printf(“n %d”,s); /s=54n列:列:aij*(p+i*n+j)pi*n+j123456789101112 多维数组的指针作函数参数维数组的指针作函数参数
37、用于接受实参数组地址的形参可用两种:用于接受实参数组地址的形参可用两种:行指针行指针和和列指列指针针。 以方阵转置为例:以方阵转置为例:例t10-13-1.c void at(int void at(int ( (* *p)3p)3) ) 用行指针用行指针 int i,j,t; int i,j,t; 缺点:不通用(必须制定列数)缺点:不通用(必须制定列数) for(i=0;i3;i+)for(i=0;i3;i+) for(j=i+1;j3;j+) for(j=i+1;j3;j+) t=pij; pij=pji; t=pij; pij=pji; pji=t; pji=t; p p指向一个包含指向
38、一个包含3 3个整形元素的一维数组(行指针),个整形元素的一维数组(行指针),p p相相当于一个二维数组!当于一个二维数组!用列指针:用列指针:例t10-13-2.c void at(int void at(int * *p p,int ,int n n) /n) /n为列数为列数 int i,j,t; int i,j,t; for(i=0;i for(i=0;in n;i+);i+) for(j=i+1;j for(j=i+1;jn n;j+);j+) t= t=pipi* *n+jn+j; ; pipi* *n+jn+j= =pjpj* *n+in+i; ; pjpj* *n+in+i=t
39、;=t; 优点:通用 在编通用函数时,一般使用列指针。用列指针:用列指针:例t10-13-3.c int sum(int int sum(int * *p p,int ,int m m,int ,int n n) /m) /m行行n n列列 int i,j,s=0; int i,j,s=0; for(i=0;im;i+) for(j=i;jn;j+) s+=pi*n+j; 或或 s+=*(p+n*i+j) return(s); 优点:通用 在编通用函数时,一般使用列指针。10104 4 字符串的指针和指向字符串的指针变量字符串的指针和指向字符串的指针变量 字符串的表示形式字符串的表示形式 可用
40、两种方法访问字符串:可用两种方法访问字符串: 用字符数组存放字符串用字符数组存放字符串 用字符指针指向一个字符串用字符指针指向一个字符串例t10-14.cmain()main() char str5=”abc”; char str5=”abc”; 定义字符数组,并将字符串定义字符数组,并将字符串存入存入 char char * *p=str; p=str; 定义指针变量,指向字符串定义指针变量,指向字符串 printf(“%s”,str); printf(“%s”,str); 通过数组名访问字符串通过数组名访问字符串 printf(“%s”,p); printf(“%s”,p); 通过指针变量
41、访问字符串通过指针变量访问字符串 printf(“%c”,printf(“%c”,* *(p+2); (p+2); 通过指针变量访问字符通过指针变量访问字符 strab c0abc010001000p 与其它一维数组的指针相比,字符串的指与其它一维数组的指针相比,字符串的指针有其针有其独特之处独特之处: 可以通过指针对字符串进行整体访问。可以通过指针对字符串进行整体访问。 对字符串的操作依赖于对字符串的操作依赖于结束符结束符。 可以可以整体赋初值整体赋初值。 有各种字符串处理函数。有各种字符串处理函数。 本节重点掌握:本节重点掌握: 通过数组和通过指针操作字符串的通过数组和通过指针操作字符串的
42、基本方法。基本方法。 常用的字符串处理方法。常用的字符串处理方法。 例:字符串拷贝操作。例:字符串拷贝操作。例t10-15-1.c,例t10-15-2.cmain() char a=”abcdef”,b20; int i; for(i=0; *(a+i)!=0; i+) *(b+i)=*(a+i); *(b+i)=0; printf(“%s”,b);main() char a=”abcdef”,b20,*p1, *p2; p1=a; p2=b; for( ; *p1!=0;p1+,p2+) *p2=*p1; *p2=0; printf(“%s”,b);用指针变量处理将拷贝操作编成一函数:将拷贝
43、操作编成一函数:例t10-15-3.c,例t10-15-4.cvoid copy_string(char *from,char *to) for(; *from; from+,to+) *to=*from; *to=0;还可以改成:还可以改成:void copy_string(char *from,char *to) for(; *from;) *to+=*from+; *to=0;字符串合并函数:字符串合并函数:例t10-16.c,void append_string(char void append_string(char * *from,char from,char * *to)to)
44、for(; for(;* *to; to+);to; to+); for(; for(; * *from;) from;) * *to+=to+=* *from+;from+; * *to=0;to=0; 阅读程序:阅读程序:例t10-17.cvoid f (char *c) main() c+=2; char c20=”abcdef”; (*c)+; f(c+1); c+; *c=0; printf(“%s”,c); 内存空间的动态分配内存空间的动态分配 在程序设计中,对于要处理的批量数据,在程序设计中,对于要处理的批量数据,我们往往是选用数组作为存放这些数据的数据我们往往是选用数组作为存放
45、这些数据的数据结构,然而,数组有一个明显的缺点,就是在结构,然而,数组有一个明显的缺点,就是在定义数组时,其长度必须是常值,无法根据需定义数组时,其长度必须是常值,无法根据需要动态地定义。这样,在很多情况下,不是定要动态地定义。这样,在很多情况下,不是定义的数组长度不够,就是定义太长以至于浪费。义的数组长度不够,就是定义太长以至于浪费。 采用动态分配可以克服这一缺点,并且可采用动态分配可以克服这一缺点,并且可以随时释放。以随时释放。 动态分配内存空间步骤:动态分配内存空间步骤: 定义一指针变量。定义一指针变量。 申请一片内存空间,并将其首地址赋给指针变量。申请一片内存空间,并将其首地址赋给指针
46、变量。此时便可通过指针变量访问这片内存;不成功则返回地址此时便可通过指针变量访问这片内存;不成功则返回地址为为0 0 用完后释放这片内存空间。用完后释放这片内存空间。 int int * *p;p; p= p=mallocmalloc( (字节数字节数);); freefree(p);(p);sizeofsizeof( (类型类型):):返回该类型数据在当前编译系统中所占的返回该类型数据在当前编译系统中所占的字节数。字节数。以上函数的原形在以上函数的原形在stdio.hstdio.h中中。p例:对例:对n n个学生的分数排序后输出。个学生的分数排序后输出。例t10-18.c #include
47、“stdio.h”#include “stdio.h”void sort(int void sort(int * *a, int n) a, int n) main()main() int int * *a,j,n;a,j,n; scanf(“%d”,&n); scanf(“%d”,&n); a= a=mallocmalloc(n(n* *sizeofsizeof(int);(int); if(!a) exit(0);if(!a) exit(0); for(j=0;jn;j+) scanf(“%d”,a+j); for(j=0;jn;j+) scanf(“%d”,a+j); s
48、ort(a,n); sort(a,n); for(j=0;jn;j+) printf(“%5d”,aj); for(j=0;jy) z=x; else z=y; return(z);main() int (*p)(); 定义指向函数的指针变量定义指向函数的指针变量p p int a,b,c; p=max; 将将p p指向函数指向函数maxmax scanf(“%d%d”,&a,&b); c=(*p)(a,b); 通过通过p p调用函数调用函数maxmax 等效于等效于c=max(a,b);c=max(a,b); printf(“n %d”,c);例t10-19.c把指向函数的指
49、针变量作为函数参数把指向函数的指针变量作为函数参数 指向函数的指针变量最常见的用途是把它指向函数的指针变量最常见的用途是把它作为函数的参数,用于接受主调函数传来的某作为函数的参数,用于接受主调函数传来的某一函数的入口地址,从而在被调函数中可以通一函数的入口地址,从而在被调函数中可以通过该指针变量调用它所指向的函数,这样,被过该指针变量调用它所指向的函数,这样,被调函数中就可实现非固定函数的调用,以达到调函数中就可实现非固定函数的调用,以达到编写通用函数的目的。编写通用函数的目的。 例:用矩形法编写一个通用的求定积分的函数。例:用矩形法编写一个通用的求定积分的函数。关键问题:如何处理被积函数是未知的。关键问题:如何处理被积函数是未知的。double intgral (double a,double b,int n,double intgral (
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年教育培训机构教师劳动协议
- 2024招生中介服务协议样例
- 2024年离婚协议:不考虑财产分割
- 2024年不动产抵押借款协议
- 2024年专项设备售后服务保修协议
- 2024年房产买卖债务处理协议
- 2024年商业合作保证协议
- 2024年度餐饮经营外包协议条款
- 人教版初中生物总复习
- 2024年11月绍兴市2025届高三选考科目诊断性考试(一模) 政治试卷(含答案)
- 《输卵管绝育术》课件
- 城管行政执法培训讲义
- 智慧城市数字孪生解决方案
- 建信融通数字证书使用承诺函范本
- 胺碘酮在急诊合理应用
- 离港系统技术培训
- 跨境电商交际英语(修订版) 课件 UNIT-2-Asking-about-Products
- 非暴力沟通(完整版)
- 天翼云认证开发工程师必备考试复习题库(高分版)-下(多选、判断题)
- 常见词牌介绍
- 广东省省级政务信息化服务预算编制标准(运维服务分册)
评论
0/150
提交评论