c语言指针课件

上传人:re****.1 文档编号:580621517 上传时间:2024-08-29 格式:PPT 页数:81 大小:1,006KB
返回 下载 相关 举报
c语言指针课件_第1页
第1页 / 共81页
c语言指针课件_第2页
第2页 / 共81页
c语言指针课件_第3页
第3页 / 共81页
c语言指针课件_第4页
第4页 / 共81页
c语言指针课件_第5页
第5页 / 共81页
点击查看更多>>
资源描述

《c语言指针课件》由会员分享,可在线阅读,更多相关《c语言指针课件(81页珍藏版)》请在金锄头文库上搜索。

1、第第9 9章章 指指 针针特特 点点能直接对内存地址操作能直接对内存地址操作, , 使用灵活使用灵活实现动态存储管理实现动态存储管理可以使程序简洁、紧凑、高效可以使程序简洁、紧凑、高效用间接访问的方式改变数据的逻辑顺序用间接访问的方式改变数据的逻辑顺序调用函数时可实现变量的引用传递调用函数时可实现变量的引用传递地址和指针的地址和指针的概念概念变量的地址和变量的值变量的地址和变量的值int i=3;float j=6;double k=9;3 36.06.09.09.0变量变量i变量变量j变量变量k2200220622022214 程序中定义的变量程序中定义的变量, 系统根据它的系统根据它的类型

2、给它分配一定长度的内存单元类型给它分配一定长度的内存单元, 该该内存单元的起始地址即为变量的地址。内存单元的起始地址即为变量的地址。该该内存单元的内容就是变量的值。内存单元的内容就是变量的值。直接访问和间接访问直接访问和间接访问直接访问:直接访问:用变量名直接从它对应的地址存取内容。用变量名直接从它对应的地址存取内容。如如: int x=5,y=8,z=0; z =x+y; 5 58 80 0变量变量x变量变量y变量变量z22002202220413直接从直接从 x 和和 y 对应的地址对应的地址2200和和2202取出内容取出内容5和和8然后相加将结果然后相加将结果13存入存入变量变量 z

3、对应的地址对应的地址2204的单元中。的单元中。间接访问间接访问定义一个存放地址的变量定义一个存放地址的变量p (p的地址的地址1500), 将将x的地址的地址2200存放在变量存放在变量 p 中。通过中。通过变量变量p取出地址取出地址2200, 再按此再按此地址存取其中的内容地址存取其中的内容, 就间接就间接的完成了对的完成了对x的存取。的存取。当当p的内容改为的内容改为2202时时, 通过通过变量变量p取出地址取出地址2202, 再按此再按此地址地址, 存取的就是变量存取的就是变量y的内的内容。容。p就是指针变量就是指针变量580变量x变量y变量z22002202220422001500变

4、量p22022202指针变量的定义指针变量的定义一般形式一般形式:基类型名基类型名 *指针变量名指针变量名说明说明:基类型名基类型名: 指针变量所指向的变量的类型名称指针变量所指向的变量的类型名称指针变量名指针变量名: 所定义的指针变量的名称所定义的指针变量的名称*: 表示它后面的变量名是指针类型表示它后面的变量名是指针类型功能功能:(1)定义该指针变量名为指向基类型的指针变量定义该指针变量名为指向基类型的指针变量,为为该变量分配存储单元该变量分配存储单元, 其长度等于存储地址的字节数。其长度等于存储地址的字节数。(2) 基类型确定用指针变量基类型确定用指针变量“间接间接”存取数据的存储单存取

5、数据的存储单元个数和存储形式。该变量只能指向基类型数据。元个数和存储形式。该变量只能指向基类型数据。指针变量的初始化指针变量的初始化用用 =&变量名变量名 来给指针变量赋初值。选项中的变量名必须来给指针变量赋初值。选项中的变量名必须是已定义过的是已定义过的,其类型必须与基类型一致。表示将它对应的地其类型必须与基类型一致。表示将它对应的地址值赋给所定义的指针变量。址值赋给所定义的指针变量。例如例如: int x,p=&x;int x,*p=&x;int x; float *p=&x; 可以用赋值语句给指针变量赋值:可以用赋值语句给指针变量赋值:float y, *py; py=&y;指针变量的引

6、用指针变量的引用引用指针变量的指针值引用指针变量的指针值与引用其它与引用其它类型的变量一样类型的变量一样直接用它的变量名直接用它的变量名引用指针变量所指向的变量时引用指针变量所指向的变量时, 用用“*指针变量名指针变量名”注意:注意:指针变量的值与它所指向变量的值指针变量的值与它所指向变量的值之间的差别之间的差别指针变量只有正确赋值后才能通过它访问指向的变量。指针变量只有正确赋值后才能通过它访问指向的变量。xint x;pp=&x;&xint *p;*p*p=5;5指针变量的运算指针变量的运算1. &: 取地址运算符取地址运算符, 取右边变量的地址取右边变量的地址2. * : 指指向向运算符运

7、算符(间接访问运算符间接访问运算符), 访问指针变量右边所指向的变量。访问指针变量右边所指向的变量。&a是变量是变量a的地址的地址*p 是指针变量是指针变量p指向的变量。指向的变量。说明说明: “&”和和“*”都是单目运算符都是单目运算符, 它们的优先级它们的优先级 相同相同, 按自右而左方向结合。按自右而左方向结合。如果已定义如果已定义 float a, *p=&a ; 则则 *p是变量是变量 a&*p 是变量是变量a的地址的地址 p&*p 等价于等价于 p而而 &a是变量是变量a的地址的地址 p*&a是是p所指向的变量所指向的变量 a*&a等价于等价于a注意注意(1). 指针变量定义和引用

8、指向变量的指针变量定义和引用指向变量的“*”含义有差别。含义有差别。(2).不能引用没有赋值的指针变量不能引用没有赋值的指针变量,不要误认为不要误认为p定义后定义后 变量变量*p就已存在就已存在,必须给必须给p正确赋值后正确赋值后,变量变量*p才存在。才存在。 (3).p=&a;是给指针变量是给指针变量p 赋值赋值, *p=3; 是给是给p指向的变量指向的变量 赋值。两者含义完全不同。赋值。两者含义完全不同。(4).给指针变量赋值必须用同类型的指针。给指针变量赋值必须用同类型的指针。(5).指针变量只存放地址指针变量只存放地址, 地址值是无符号整数地址值是无符号整数, 但不能直但不能直 接用整

9、型量接用整型量(或其它非地址量或其它非地址量)赋值给指针变量。赋值给指针变量。int *p1=2200;给变量赋值的两种方法给变量赋值的两种方法1. 直接访问直接访问用变量名用变量名如如: int i; i=5;2. 间接访问间接访问通过指向变量通过指向变量i的地址的指针变量的地址的指针变量 p 赋值赋值如:如:int i, *p; p=&i; *p=5;取地址运算符取地址运算符&和指向运算符和指向运算符*的应用的应用main( ) int m, n; int *p=&m,*q=&n; printf(Input m,n:); scanf(%d %d,p,&n); printf(m=%d &m=

10、%Xn,m,&m); printf(*p=%d p=%Xn,*p,p); printf(n=%d &n=%Xn,n,&n); printf(*q=%d q=%Xn,*q,q);运行结果运行结果:Input m,n: 123 456 m=123 &m=FFD6*p=123 p=FFD6n=456 &n=FFD8*q=456 q= FFD8 int x,y;xyp1pp2 int *p, *p1, *p2; p1=&x; p2=&y;&x&y86 x=8; y=6; printf(min=%d, max=%dn,*p1,*p2); p1=p2; &y if ( xy ) p=p1;&x p2=p;

11、 &xmain( )运行结果运行结果: : min=6, max=8例:例:通过交换指针变量值按大小顺序输出通过交换指针变量值按大小顺序输出指针变量作为函数的参数指针变量作为函数的参数以指针类型为函数的参数以指针类型为函数的参数,作用作用是将变量是将变量的地址传入函数。的地址传入函数。int x,y;int *pt1;*pt2;x=8;y=6;pt1=&x;pt2=&y;if (xy) swap(pt1,pt2);printf(x=%d, y=%dn,x,y);swap(int *p1,int *p2)p=*p1;*p1=*p2;*p2=p; int p;p8pt1pt2xy main() &

12、x&yp1p2&x&y8668运行结果运行结果: x=6, y=8int x,y;int *pt1;*pt2;x=8;y=6;pt1=&x;pt2=&y;if (xy) swap(pt1,pt2);swap(int *p1,int *p2)p=*p1;*p1=*p2;*p2=p; int p;printf(x=%d, y=%dn,x,y);指针与数组指针与数组C语言中规定语言中规定数组名是指针类型的符号常量数组名是指针类型的符号常量, 该符号常量值该符号常量值等于数组首元素的地址等于数组首元素的地址 ( 简称数简称数组首地址组首地址) ,它的它的类型是指向数组元素的指针类型类型是指向数组元素的

13、指针类型。即即数组名是指向该数组首元素的指针常量数组名是指向该数组首元素的指针常量。指向数组元素的指针指向数组元素的指针1.定义指向数组元素的指针变量定义指向数组元素的指针变量定义指向数组元素的指针变量与定义指向变量的指针变量的定义指向数组元素的指针变量与定义指向变量的指针变量的方法相同方法相同.如如:int a10;int *p; p=&a0; 由于数组名是指向由于数组名是指向0号元素的指针类型符号常量号元素的指针类型符号常量, 所以所以a与与&a0相等相等。p=&a0; p=a; 两句等价两句等价p=a不是把不是把a的各元素赋给的各元素赋给p注意数组名与指针变量的区别注意数组名与指针变量的

14、区别指针运算指针运算 指针变量可以加减一个整数指针变量可以加减一个整数,两个同类型指针可以两个同类型指针可以 相减相减得到一个整数。得到一个整数。指针变量每增减指针变量每增减1, 地址值增减量等于所指向地址值增减量等于所指向的变量类型的字节数的变量类型的字节数sizeof(type), 将它称作地址步进单位将它称作地址步进单位d。当当指针变量指向数组元素指针变量指向数组元素时时, 指针变量每加减指针变量每加减1,表示指针前表示指针前后移动后移动1个元素个元素, 地址值增减地址值增减d。如如: int a10,*p; p=a; p+; p+=3; 注意注意: 指针变量的运算顺序。指针变量的运算顺

15、序。+*p,*p+,*(+p),(*p)+ 四者之间的差别:四者之间的差别:+*p先给先给p指向的变量加指向的变量加1,然后取其值然后取其值(*p)+先取先取p指向的变量值指向的变量值, 然后该变量值加然后该变量值加1*p+取取p所指向变量的值所指向变量的值, 然后然后p增增1*+pP先增先增1, 然后取然后取p所指向变量的值所指向变量的值main()main()int a4=1,2,3,4,b,c,d,e;int a4=1,2,3,4,b,c,d,e; int *p=a; int *p=a; b=*p+; b=*p+; printf( printf(“n%d,%d,n%d,%d,”,b,*p

16、);,b,*p); c=*+p; c=*+p; d=+*p; d=+*p; printf( printf(“%d,%d%d,%d”,c,d);,c,d); 运行结果运行结果1,2,3,41,2,3,4通过指针引用数组元素通过指针引用数组元素在在 int a10,*p=a; 定义的情况下定义的情况下:(1) p+i或或a+i就是就是ai的地址的地址。都要进行。都要进行a+id的运算。的运算。(2) *(p+i)或或*(a+i)就是就是p+i或或a+i所指向的数组元素所指向的数组元素ai。 数组元素中的数组元素中的 “ ” 是变址运算符是变址运算符, 相当于相当于*( + ) , ai 相当于相当

17、于*(a+i)。(3) 指向数组元素的指针变量也可带下标指向数组元素的指针变量也可带下标, 如如 pi与与*(p+i)等价。等价。 所以所以, ai,*(a+i) ,pi,*(p+i) 四种表示法全部等价。四种表示法全部等价。(4) 注意注意p与与a的差别的差别,p是变量是变量a是符号常量是符号常量,不能给不能给a赋值赋值, 语句语句a=p; a+; 都是错的。都是错的。p &a0a9a1a2aia0p+1,a+1p+2,a+2 p+i,a+ip+9,a+9a引用数组元素可用引用数组元素可用: :1)下标法下标法,如如ai,pi。2) 指针法指针法,如如*(p+i)或或*(a+i),其中其中p

18、是是指向数指向数组组a a的元素的指针变量。的元素的指针变量。main( ) int a10; int *p,i; for(p=a;p(a+10);p+) scanf(%d, p); printf(n); for(i=0;i10;i+) printf(%d, ai); for(i=0;i10;i+) printf(%d, *(a+i); p=a; /*不能省略不能省略*/ for(i=0;i10;i+,p+) printf(%d, *p); for(p=a;p(a+10);p+) printf(%d,*p); 例例. .输入输入/ /输出数组全部元素输出数组全部元素用字符型指针访问字符数组和字

19、符串用字符型指针访问字符数组和字符串【例【例9.59.5】用字符型数组名和】用字符型数组名和字符指针变量字符指针变量 两种方法整体输入两种方法整体输入/ /输出字符串。输出字符串。 main() char s81=Hello!,*p=s; char *ps=Welcome to you!; printf(%sn,s); printf(%sn,ps); gets(s); printf(%sn,s); gets(p); printf(%sn,s); 字符指针变量和字符数组的区别字符指针变量和字符数组的区别(1) 存储的内容不同存储的内容不同:字符数组存储着字符串的内容字符数组存储着字符串的内容,

20、而字符指针变量而字符指针变量存放的是字符串首元素的地址存放的是字符串首元素的地址,不是它的内容。不是它的内容。(2) 分配的内存单元不同分配的内存单元不同:字符数组分配一段有确定地址的内存。而指针变字符数组分配一段有确定地址的内存。而指针变量只分配存放地址的内存单元量只分配存放地址的内存单元,该指针变量可以该指针变量可以指向一个字符型数据指向一个字符型数据,但若未赋初值但若未赋初值,则它并未指向则它并未指向一个明确的地址。此时它指向的变量并不存在。一个明确的地址。此时它指向的变量并不存在。(3) 赋值方法不同赋值方法不同:对字符数组只能在定义时整体赋初值对字符数组只能在定义时整体赋初值, 不能

21、用赋值语句不能用赋值语句整体赋值。赋值语句只能对各个元素分开赋值。整体赋值。赋值语句只能对各个元素分开赋值。如如: char s16; s=I am a student.;char s16=I am a student.;对字符指针变量对字符指针变量, 可以采用下面方法赋值可以采用下面方法赋值: char *p; p=I am a student.;(4) 指针变量的值是可以改变的指针变量的值是可以改变的, 字符数组名是地址常量其值是不能改变的。字符数组名是地址常量其值是不能改变的。数组或指针变量作函数参数数组或指针变量作函数参数如如:main( ) f(int a , int n) int

22、array10; . . . . . . f(array,10) . . .由于由于数组名代表数组名代表首地址首地址,能接收并存放地址值的只能能接收并存放地址值的只能是指针变量。故编译系统将形参是指针变量。故编译系统将形参数组名作为数组名作为指针变量指针变量来处理。例中函数首部来处理。例中函数首部 f(int a , int n)可写成可写成 f(int *a, int n) 两种完全等价。两种完全等价。 归纳起来归纳起来, ,如果有一个数组如果有一个数组, ,想在被调用的函数中想在被调用的函数中改变其元素的值改变其元素的值, ,实参与形参的对应关系有以下四种实参与形参的对应关系有以下四种:

23、:(1).实参和形参都用数组名。实参和形参都用数组名。(2).实参用数组名实参用数组名, 形参用指针变量。形参用指针变量。(3).实参用指针变量实参用指针变量, 形参用数组名。形参用数组名。(4).实参和形参都用指针变量。实参和形参都用指针变量。实质都是实质都是地址值的传递地址值的传递【例【例9.7】通过调用函数通过调用函数, 将整型数组的所有元素将整型数组的所有元素加加10。参数传递用四种方法实现。参数传递用四种方法实现。void add(int b , int n) int i; for(i=0; in; i+) bi+=10;main( ) int i, a10= 1,2,3,4,5,6

24、,7,8,9,10; add(a,10); for(i=0; i10; i+) printf(%4d,ai);void add(int *p, int n) int *pend=p+n; for(; ppend; p+) *p+=10;main( ) int i, a10= 1,2,3,4,5,6,7,8,9,10; add(a,10); for(i=0; i10; i+) printf(%4d,ai);void add(int b , int n) int i; for(i=0; in; i+) bi+=10;main( ) int i, a10= 1,2,3,4,5,6,7,8,9,10;

25、 int *q=a; add(q,10); for(i=0; i10; i+) printf(%4d,ai);void add(int *p, int n) int *pend=p+n; for(; ppend; p+) *p+=10;main( ) int i, a10= 1,2,3,4,5,6,7,8,9,10; int *q=a; add(q,10); for(i=0; i10; i+) printf(%4d,ai);用字符数组或指针做函数参数传递字符串用字符数组或指针做函数参数传递字符串将字符串从一个函数传递到另一个函数将字符串从一个函数传递到另一个函数, 可以用可以用地址传递地址传递

26、的方法的方法, 即用即用字符数组名字符数组名或用字符指针变量或用字符指针变量作参数。在被调用的函作参数。在被调用的函数中可以改变字符串中的内容数中可以改变字符串中的内容, 在主调函数在主调函数中可以得到改变了的字符串。中可以得到改变了的字符串。【例【例9.89.8】 字符串复制函数主要功能的实现。字符串复制函数主要功能的实现。 (1)用字符数组作参数用字符数组作参数void strcpy(char s1 ,char s2 ) int i=0; while(s2i!=0) s1i=s2i; i+; s2i=0; main( ) char a20=I am a teacher.; char b =

27、you are a srudent.; printf(string a=%sn string b=%sn,a,b); strcpy (a,b); printf(n string a=%sn string b=%sn,a,b); (2)形参用字符指针变量。)形参用字符指针变量。程序如下:程序如下:void strcpy(char *s1, char *s2) for( ; *s2!=0; s2+, s1+) *s1=*s2; *s1=0;main( ) char a20=I am a teacher.; char *b=you are a srudent.; printf(string a=%s

28、n string b=%sn,a,b); strcpy(a,b); printf(n string a=%sn string b=%sn,a,b); while( *s1=*s2)!=0 ) s1+; s2+; *s1=0; while( *s2!=0 ) *s1+=*s2+; *s1=0; while( *s2 ) *s1+=*s2+; *s1=0; while( *s1+=*s2+)!=0 ) while( *s1+=*s2+ ) 多维数组和指向分数组的指针多维数组和指向分数组的指针多维数组的地址多维数组的地址以二维数组为例以二维数组为例,设二维数组设二维数组a有有3行行4列。列。 int

29、 a34=1,2,3,4,5,6,7,8,9,10,11,12a是数组名是数组名, a数组有数组有3行行, 即即3个分数组个分数组:a0,a1,a2。每个分数组又是含每个分数组又是含4个列元素的一维数组个列元素的一维数组 。a22a12a02a23a21a20a13a11a10a03a01a00a0a1a22000a00a01a02a03a10a11a12a13a20a21a22a23a2000Ha+12008a+22010a0+1*(a+0)+1a1+1*(a+1)+1a2+1*(a+2)+1200A20122002基类基类型型行指针行指针与列指与列指针针a23*(a2+3)*(*(a+2)

30、+3) +3 +2 +1 +0a0 a0a0a0*(a+0)*(a+0)*(a+0)*(a+0) +3 +2 +1 +0a1 a1a1a1*(a+1)*(a+1)*(a+1)*(a+1)注意注意 a+1与与a0+1不同不同a+1是是a第第1行分数组地址行分数组地址*(a+1)是第是第1行数组名行数组名*(a+1)是元素是元素a10 a0是第是第0行分数组名行分数组名a0+1是是元素元素a01 地址地址*(a0+1)是是元素元素a01 形式形式 含义含义 内容内容a ,&a0 二维数组名二维数组名,0行分数组地址行分数组地址 1000a0,*(a+0),*a ,&a00 0行一维数组名行一维数组

31、名, ,0行行0列元素地址列元素地址 1000a0+1,*a+1,&a01 0行行1列元素地址列元素地址 1002a+1,&a1 1行一维数组首地址行一维数组首地址 1008a1,*(a+1) ,&a10 1行一维数组名行一维数组名,1,1行行0 0列元素地址列元素地址 1008a1+3,*(a+1)+3,& &a13 1行行3 3列元素地址列元素地址 1014*(a2+3),*(*(a+2)+3),a23 2行行3 3列元素列元素 12注意注意: a和和a0的地址均为的地址均为1000但不等价但不等价,a+1和和a0+1不等。不等。指向多维数组的指针指向多维数组的指针1.指向多维数组元素的指

32、针指向多维数组元素的指针例:用指针变量输出数组元素的值。例:用指针变量输出数组元素的值。main( ) int a34=1,2,3,4,5,6,7,8,9,10,11,12; int *p; for (p=a0;pa0+15;p+) if(p-a0)%5=0) printf(n); printf(%4d,*p); 定义形式:定义形式: 数据类型数据类型 (*指针名指针名)一维数组维一维数组维数数;一维数组指针变量维数和二维数组一维数组指针变量维数和二维数组列数必须相同。列数必须相同。例:例:int a34, (*p)4=a;2.指向分数组的指针指向分数组的指针a22a12a02a23a21a2

33、0a13a11a10a03a01a00a00a01a02a03a10a11a12a13a20a21a22a23a2000a+12008a+22010p0+1p或*p+1p1+2p+1或*(p+1)+2p+2int a34;int (*p)4=a;例:用指向二维数组的分数组的指针变量,按行输出。例:用指向二维数组的分数组的指针变量,按行输出。main( ) int a34=1,2,3,4,5,6,7,8,9,10,11,12; int *q,(*p)4; for(p=a;pa+3;p+) for(q=*p;q*p+4;q+) printf(%5d,*q); printf(n); 注意注意: in

34、t (*p)5; 表示表示p是一个指针变量是一个指针变量,可以指向含有可以指向含有5个元素的一维数组,其中每个元素都是整型的。个元素的一维数组,其中每个元素都是整型的。 如果定如果定义为义为 int *p5; 由于由于 “ ” 优先级高优先级高, 则表示则表示p首先是首先是数组数组,它有它有5个元素个元素, 每个元素为指向整型变量的指针。每个元素为指向整型变量的指针。 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 9 9 10 11 12 10 11 12q q+2pp+2用多维数组名和指针变量作函数参数用多维数组名和指针变量作函数参数(1)用多维数组名作实参或形参。用多维数

35、组名作实参或形参。如如: f(int a 4, int n);(2)用指向元素的指针变量作实参或形参。用指向元素的指针变量作实参或形参。如如: f1(int *p);(3)用指向分数组的指针变量作函数参数。用指向分数组的指针变量作函数参数。如如:f2(int (*q)4, int m);【例【例9.169.16】 用两个二维数组存储矩阵,调用函数求两个用两个二维数组存储矩阵,调用函数求两个矩阵之差,差矩阵存放在第一个实参数组中,用指向分数矩阵之差,差矩阵存放在第一个实参数组中,用指向分数组的指针变量作形参。矩阵输出也用函数实现。组的指针变量作形参。矩阵输出也用函数实现。 #define N 4

36、sub(int (*p1)N,int (*p2)N,int m) int *q1,*q2,(*u)N; u=p1+m; for(;p1u;p1+,p2+) for(q1=*p1,q2=*p2;q1*p1+N;q1+,q2+) *q1-=*q2;print(int (*p)N,int m) int *q,(*u)N; u=p+m; for(;pu;p+) for(q=*p;q*p+N;q+) printf(%6d,*q); printf(n); printf(n);main() int i,j,a N=1,2,3,4,5,6,7,8 ; int b N=10,20,30,40,50,60,70,

37、80; print(a,2); print(b,2); sub(b,a,2); print(b,2); 指针数组指针数组 如果每个数组元素均为指针类型的变量,即如果每个数组元素均为指针类型的变量,即数组元数组元素的类型是指针类型素的类型是指针类型,则称这样的数组为,则称这样的数组为指针数组指针数组。 一维指针数组的定义形式为:一维指针数组的定义形式为:基类型名基类型名 * *数组名数组名 数组长度数组长度 =地址初值列表地址初值列表 例如:例如:int i,j,k,m,n;int *q5=&i,&j,&k,&m,&n; main() char a =Program; char b =Fortr

38、an; char c =Basic; char *p4; p0=a; p1=b; p2=c; p3=NULL;p0p1p2p3char *p4Basic0P r o g r a m0F ortra n00或或:main() char *p4; p0= Program; p1= Fortran; p2= Basic; p3=NULL;初始化初始化:main() char *p =Program, Fortran, Basic,NULL;用指针数组处理多个字符串用指针数组处理多个字符串例:将5个字符串递增排序后输出。#include #include main() char *pccolor =r

39、ed, blue, yellow, green, purple; int n=5; printf(Before sorting is:n); OutPut(pcolor,n); Sort(pcolor,n); printf(After sorting is:n); OutPut(pcolor,n);void Sort(char *a , int n)int i,j,k; char *t;for(i=0;in-1;i+)for(j=i+1;j0)void OutPut(char *a ,int n)int i;for(i=0;in;i+)printf(%sn,ai);0der0neerg0eul

40、b0wolley0elpruppcolor4pcolor3pcolor2pcolor1pcolor00der0neerg0eulb0wolley0elpruppcolor4pcolor3pcolor2pcolor1pcolor0排排序序前前排排序序后后指向指针的指针指向指针的指针(二级指针二级指针)指针变量中存放一级指针变量的地址指针变量中存放一级指针变量的地址例例 int *p1; int *p2; int i=3; p2=&i; p1=&p2; *p1=5;p1P2(指针变量指针变量) i(整型变量整型变量)二级指针二级指针一级指针一级指针目标变量目标变量二级间接寻址二级间接寻址&p2&i

41、5 3用指向指针的指针访问指针数组用指向指针的指针访问指针数组 通过指针变量来访问指针数组的元素,就必须定义通过指针变量来访问指针数组的元素,就必须定义指向指针的指针变量。用所定义的指向指针的指针指向指针的指针变量。用所定义的指向指针的指针变量来指向指针数组的各元素,进行间接访问。若变量来指向指针数组的各元素,进行间接访问。若要通过该指针变量来访问指针数组元素所指向的变要通过该指针变量来访问指针数组元素所指向的变量的内容,则需要进行两次间接访问。量的内容,则需要进行两次间接访问。 【例【例9.109.10】 指针数组的各元素指向整型数据的简单实例指针数组的各元素指向整型数据的简单实例 main

42、() static int s5=10,20,30,40,50; int *q5=&s0,&s1,&s2,&s3,&s4; int *p; for(p=q;pq+5;p+) printf(%dt,*p); 指针数组作指针数组作main( )函数的形参函数的形参 C C语言规定,语言规定,main() main() 函数形参是固定的,第一个形参为函数形参是固定的,第一个形参为整型,它接收实参的个数,第二个形参为字符指针数组,整型,它接收实参的个数,第二个形参为字符指针数组,它的各元素分别接收命令行输入的各字符串的首地址。它的各元素分别接收命令行输入的各字符串的首地址。 例如:例如:main(in

43、t argc,char *argv ) 形参形参argcargc接收实参的个数,接收实参的个数,字符指针数组字符指针数组argvargv接收各字符串的首地址。接收各字符串的首地址。 它的一般形式为它的一般形式为:命令名命令名 参数参数1 1 参数参数2 2 参数参数n-1n-1【例【例9.119.11】编写源程序编写源程序show.cshow.c,在命令行输入在命令行输入showshow和和 若干个字符串后,顺序分行显示这些字符串。若干个字符串后,顺序分行显示这些字符串。 show.c 的程序如下:的程序如下:main(int argc,char *argv) int i; for(i=1;i

44、0) printf(%sn,*+argv); 【例【例9.12】 编写程序编写程序echo.c,实现操作系统中的实现操作系统中的echo命令,命令,echo命令是将后面所带的参数原样显示出来。它与上例相似命令是将后面所带的参数原样显示出来。它与上例相似但不分行,所带的参数都显示在同一行。但不分行,所带的参数都显示在同一行。 main(int argc,char *argv) while(-argc0) printf(%s%c,*+argv,(argc1)? :n); 在操作系统命令行状态下输入:在操作系统命令行状态下输入: echo Welcome to you ! 执行后输出以下信息:执行后

45、输出以下信息: Welcome to you ! 【例【例9.189.18】实现系统提供的字符串复制函数】实现系统提供的字符串复制函数strcpy()strcpy()的全部功能。的全部功能。 char *strcpy(char *s1,char *s2) char *p=s1; while(*s1+=*s2+); return(p); main() char s20; printf(%sn,strcpy(s,Welcome to you!); 结构体与指针结构体与指针指向指向结构体变量结构体变量的指针的指针结构体指针变量的定义:结构体指针变量的定义:struct 结构体名结构体名 * 指针变量

46、名;指针变量名;例如:例如:struct student *pt=&stu;struct student int num; char name20; char sex; int age;stu;使用结构体指针变量使用结构体指针变量引用成员形式引用成员形式(*结构体指针名结构体指针名).成员名成员名结构体指针名结构体指针名-成员名成员名结构体变量名结构体变量名.成员名成员名struct student int num; char name20; char sex; int age;stu;struct student *p=&stu;(*p).nump-numstu.numagesexnamen

47、umstupp=&stu.num例例: :结构体指针的使用结构体指针的使用#include #include struct student int num; char name20; char sex; int age;main() struct student stu, *p; p=&stu; stu.num=10011; strcpy(stu.name, Kobe Bryant ); p-sex=M; p-age=33; printf(nNo:%dnname:%snsex:%cnscore:%dn, (*p).num, p-name, stu.sex, p-age);例例: :结构体数组结

48、构体数组指针的使用指针的使用struct student int num; char name20; char sex; int age;stu3= 10101, Li Lin,M,18, 10102,Zhang Fun,M,19, 10103,Wang Min,F,20;main() struct student *p; for(p=stu;pnum,p-name, p-sex,p-age);10101Li LinM18stu0pstu1stu2p+1p+210102Zhang FunM1910103Wang MinF20结构体指针作函数参数结构体指针作函数参数 用结构体变量的成员作参数用结

49、构体变量的成员作参数-单单值传递值传递 用结构体变量作参数用结构体变量作参数-多多值传递值传递用指向结构体变量或数组的指针作参数用指向结构体变量或数组的指针作参数 - -地址地址传递。传递。【例【例9.179.17】 采用采用“引用传递引用传递”的方式,用指向结构体的方式,用指向结构体的指针变量作参数,在的指针变量作参数,在inputinput函数中输入并计算平均成函数中输入并计算平均成绩,在绩,在mainmain函数输出。函数输出。 #define N 4#include#define FMT %5d %-11s%5d%8d%8d%10.1fnstruct st int num; char

50、name11; int s3; float aver;void input(struct st *p)scanf(%d%s%d%d%d,&p-num,p-name,&p-s0,&p-s1,&p-s2); p-aver=(p-s0+p-s1+p-s2)/3.0;main() struct st aN,*p=a; printf(Input student:number name score1 score2 score3n); while(pa+N) input(p+); printf(number name score1 score2 score3 averagen); for(p=a;pnum,

51、p-name,p-s0,p-s1,p-s2,p-aver); 指针与链表指针与链表链表可以动态的进行存储分配链表可以动态的进行存储分配1249head1249A13561356B14751475C10211021DNULLhead: 头指针头指针,存放一个地址存放一个地址,指向链表中的第一个元素指向链表中的第一个元素.每一个元素称为一个每一个元素称为一个“结点结点”,每个结点都包括两部分每个结点都包括两部分:1.用户需要的实际数据用户需要的实际数据;2.下一个结点的地址下一个结点的地址.表尾表尾: 它的地址部分放一个它的地址部分放一个“NULL”,链表到此结束链表到此结束.可用可用结构体类型的

52、变量结构体类型的变量来存储链表中的来存储链表中的结点元素结点元素.1249head1249A13561356B14751475C10211021DNULL每一个结点中存放地址的部分可用每一个结点中存放地址的部分可用指针指针来实现来实现.例例: struct student int num; float score; struct student *next; ;简单静态链表简单静态链表# define NULL 0struct student long num; float score; struct student *next; ;main( ) struct student a,b,c,*

53、head,*p; a.num=9901; a.score=89.5; b.num=9903; b.score=90; c.num=9905; c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; do printf(“%ld %5.2f n”,p-num,p-score); p=p-next; while(p!=NULL);anumscorenextbchead p990189.5990390990585&a&b&cNULL&a&b&cNULL动态链表动态链表处理动态链表所需的函数处理动态链表所需的函数1. malloc

54、 函数函数void *malloc (unsigned int size);作用是作用是: 在内存的动态存储区分配一个长度为在内存的动态存储区分配一个长度为size的连续空间的连续空间原型说明在原型说明在“stdlib.h”头文件和头文件和“alloc.h”头文件中头文件中2.calloc函数函数 void *calloc(unsigned n,unsigned size);作用是作用是: 在内存的动态区分配在内存的动态区分配n个长度为个长度为size的连续空间的连续空间.3. free函数函数void free(void *p);作用是作用是: 释放由释放由p指向的内存区指向的内存区.typ

55、edef struct Node int data; struct Node *next;Node;链表的插入操作链表的插入操作ses-next=pre-next;pre-next=s;顺序可以顺序可以颠倒吗?颠倒吗?a1a2ai-1aianpreh void InsList(Node *L,int i,int e) Node *pre,*s; int k=0; pre=L; while(pre!=NULL&knext; k=k+1; if(k!=i-1) printf(“插入位置不合理!插入位置不合理!”); return; s=(Node*)malloc(sizeof(Node); s-d

56、ata=e; s-next=pre-next; pre-next=s; 链表的删除操作链表的删除操作pre-next=pre-next-next;a1a2ai-1aianpreai+1rL free(r); void DelList(Node *L,int i) Node *pre,*r; pre=L; int k =0; while(pre-next!=NULL&knext; k=k+1; if(k!=i-1) printf(“删除结点的位置删除结点的位置i不合理!不合理!”); return ERROR; r=pre-next; pre-next=pre-next-next; free(r

57、); return OK; 建立动态链表建立动态链表头插法建表头插法建表尾插法建表尾插法建表头插法建表头插法建表sAs指向新申请的结点指向新申请的结点s-data=A;HsA插入第一个结点:插入第一个结点:插入某一个结点:插入某一个结点:HAsB从一个空表开始,重复读入数据,生成新结点,从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入将读入数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头结点之后,直至读入结束标志为止。到当前链表的表头结点之后,直至读入结束标志为止。s-next=H-next;H-next=s;顺序可以顺序可以颠倒吗?颠倒

58、吗?H初始化空表初始化空表 Linklist CreateFromHead( ) Node *s,*L; char c; int flag=1; L=(Node*)malloc(sizeof(Node); L-next=NULL; while(flag) c=getchar(); if(c!=$) s=(Node*)malloc(sizeof(Node); s-data=c; s-next=L-next; L-next=s; else flag=0; 尾插法建表尾插法建表sAs指向新申请的结点指向新申请的结点s-data=A;HsA插入第一个结点:插入第一个结点:插入某一个结点:插入某一个结点

59、:sB将新结点插到当前单链表的表尾上。将新结点插到当前单链表的表尾上。增加一个增加一个尾指针尾指针r,使之,使之指向当前单链表的表尾指向当前单链表的表尾。r-next=s;r=s;顺序可以顺序可以颠倒吗?颠倒吗?H初始化空表初始化空表rrHArr Linklist CreateFromTail() Node *L,*r, *s; int flag =1; L=(Node * )malloc(sizeof(Node); L-next=NULL; r=L; while(flag) c=getchar(); if(c!=$) s=(Node*)malloc(sizeof(Node); s-data=

60、c; r-next=s; r=s; else flag=0; r-next=NULL; 指针与函数指针与函数返回值为指针类型的函数返回值为指针类型的函数 指针函数的定义格式如下:指针函数的定义格式如下:类型名类型名 * *函数名函数名( (参数表参数表) )例如:例如:int *f(int x) 指向函数的指针指向函数的指针指针变量的另一的重要用途是指针变量的另一的重要用途是, 它它可以指向一个函数可以指向一个函数(存储函数入口地址存储函数入口地址), 通过它可以调用指向的函数通过它可以调用指向的函数, 改改变它的值就可以动态的调用不同的函数变它的值就可以动态的调用不同的函数。指向函数的指针和

61、函数参数指向函数的指针和函数参数 指向函数的指针的定义指向函数的指针的定义一般形式一般形式: 数据类型数据类型 (* 指针变量名指针变量名)( )例如例如: int (*p)( );说明说明:1.在给函数指针变量赋值时在给函数指针变量赋值时,只需给出函数名而不必给参数只需给出函数名而不必给参数;2.用函数指针调用函数时用函数指针调用函数时,只需用只需用*p代替函数名即可代替函数名即可.【例【例9.20】 指向函数的指针程序举例。指向函数的指针程序举例。#includeint f(int x) return 3*x*x+5*x-7;void main() int (*p)(); int a; p

62、=f; printf(Input x=); scanf(%d,&a); printf(*p)(a)=%dn,(*p)(a); printf(p(2a)=%dn,p(2*a); 作作 业业1.#include main( ) int a23=1,2,3,4,5,6; int m,*p; p=&a00; m=*p*(*(p+2)*(*(p+4); printf(“%dn”,m);2.#include main( ) char a =“language”,b =“program”; char *p=a,*q=b; int k; for(k=0;k7;k+) if(*(p+k)=*(q+k) printf(“%c”,*(p+k); 3.main( ) char a =“Basic”; char *p; for(p=a;pa+5;p+) printf(“%sn”,p);P195. 9.1, 9.8, 9.12

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号