C语言程序设计(第三版)课件:指针的应用_第1页
C语言程序设计(第三版)课件:指针的应用_第2页
C语言程序设计(第三版)课件:指针的应用_第3页
C语言程序设计(第三版)课件:指针的应用_第4页
C语言程序设计(第三版)课件:指针的应用_第5页
已阅读5页,还剩48页未读 继续免费阅读

下载本文档

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

文档简介

指针的应用本章主要内容1、指针与数组2、字符串的指针和指向字符串的指针变量3、指针数组4、指向指针的指针5、函数指针6、返回指针的函数7、main()函数的返回指和参数9.1一维数组与指针C语言规定数组名代表数组的起始地址,一个数组包含若干个元素,每个数组元素都在内存中占用存储空间,都有相应的地址,指针变量可以指向数组或数组元素。【例9.1】下面的程序用于演示数组元素的引用方法,请认真体会它们的联系和区别。#include"stdio.h"intmain(){inta[5],i;for(i=0;i<5;i++){scanf("%d",&a[i]);}for(i=0;i<5;i++){printf("%3d",a[i]);}printf("\n");return0;}#include"stdio.h"intmain(){inta[5],i;for(i=0;i<5;i++){scanf("%d",a+i);}for(i=0;i<5;i++){printf("%3d",*(a+i));}printf("\n");return0;}9.1.1数组名的特殊意义及其在访问数组元素中的作用9.1.2数组元素的指针inta[5],*p;p=&a[0];p=&a[0];等价于p=a;其作用是将指针变量p指向数组元素的首地址,其指向关系如图9-2(b)所示。9.1.3指针变量运算指针变量的运算是指指针变量所持有的地址为运算对象进行的运算,所以指针变量的运算实际上就是地址的运算。

指针的运算常常是针对数组元素的,因为数组在内存中是连续存放的,所以指向同一数组中不同元素的两个指针的关系运算常用于比较它们所指元素在数组的前后位置关系。指针的算术运算(增1或减1)则常用来移动指针的指向,使其指向数组中的其他元素。这里强调只有运算结果仍指向同一数组中的元素时,指针运算才有意义。1、指针加上整数

指针p加上整数j将产生指向特定元素的指针,这个特定元素是p原来指向的元素后的第j个位置。

2、指针减去整数指针p减去整数j将产生指向特定元素的指针,这个特定元素是p原来指向的元素前的第j个位置。

3、两个指针相减当两个指针相减的时候,结果为两个指针之间的距离,用数组元素的个数来表示。因此,如果p指向a[i]且q指向a[j],则p-q就等于i-j。4、指针的比较

可以用关系运算符(<、<=、>、>=)和判断运算符(==和!=)进行指针的比较运算,只有在两个指针指向同一数组时,用关系运算符进行的指针比较才有意义。比较的结果依赖于数组中两个元素的相对位置。例如:inta[10],*p,*q;p=&a[5];q=a[1];p<=q的指位0,而p>=q的结果为1。inta[5],*p;p=a;

表明定义了一个指向整形数据的指针变量p,使其指向了数组a的首地址,通过这个指针变量p就可以访问数组a的元素。

5、用指针变量访问数组元素注意:指针运算p+1和p++表面现象上看,都是对当前的指针p进行加1运算,但p+1并不改变当前指针的指向,p++表示使p的指向从当前的位置指向下一个元素。p++的偏移问题,是偏移1*sizeof(基类型)个字节。采用通过移动指针变量p来引用数组元素的方法,可将【例9.1】程序修改为#include"stdio.h"intmain(){inta[5],*p;for(p=a;p<a+5;p++){scanf("%d",p);}for(p=a;p<a+5;p++){printf("%3d",*p);}printf("\n");return0;}如果有定义:inta[5],*p;p=a;指针与数组元素的关系归纳如下:

①&a[j],a+j,p+j等价,代表a数组第j+l个元素的地址。②a[j],*(a+j),p[j],*(p+j)等价,代表a数组第j+l个元素的值。③*(p++)等价于a[j++]、*(p--)等价于a[j--]、*(++p)等价于a[++j]、*(--p)等价于a[--j]。数组元素表示方法a[0]a[1]a[2]a[3]a[9]...aa+9a+1a+2地址元素下标法a[0]a[1]a[2]a[9][]变址运算符a[i]

*(a+i)a[i]

p[i]

*(p+i)

*(a+i)*a*(a+1)*(a+2)*(a+9)inta[10];a[0]a[1]a[2]a[3]a[9]...pp+9p+1p+2地址元素指针法*p*(p+1)*(p+2)*(p+9)p[0]p[1]p[2]p[9]a[0]a[1]a[2]a[3]a[4]例数组元素的引用方法main(){inta[5],*p,i;for(i=0;i<5;i++) a[i]=i+1;

pa=a;for(i=0;i<5;i++) printf("a[%d]:%d\n",i,a[i]);for(i=0;i<5;i++) printf("*(a+%d):%d\n",i,*(a+i));for(i=0;i<5;i++) printf("p[%d]:%d\n",i,p[i]);for(i=0;i<5;i++) printf("*(p+%d):%d\n",i,*(p+i));}12345p使用指针变量是应该注意以下几问题:①不要使用没有赋值的指针变量,只用指针之前一定要对它正确的赋值。②使用指针变量访问数组元素时,要随时检查指针的变化范围和指针当前的值,使指针的指向不能超过数组的上下界。#include"stdio.h"voidmain(){inta[10],*p=a,j;for(j=0;j<10;j++){scanf("&d",p++);}for(j=0;j<10;j++){printf("%3d",*p++);}printf("\n");}#include"stdio.h"voidmain(){inta[10],*p=a,j;for(j=0;j<10;j++){scanf("&d",p++);}

p=a;for(j=0;j<10;j++){printf("%3d",*p++);}printf("\n");}③无论传递数组的首地址的函数参数用数组名还是指针,其实质都是指针,在函数被调用时,该指针通过参数传递均指向数组。【例9.3】下面的程序用于演示数组和指针变量作为函数的参数,实现的功能是输入几个学生的成绩,求其平均成绩。方法一:实参用指针变量,形参用数组名。#defineN5floataver(floatp[]){inti;floatav,s=0;for(i=0;i<N;i++)s+=p[i];av=s/N;return(av);}voidmain(){floatscore[N],av,*p=score;inti;printf("请输入5个学生的成绩!");for(i=0;i<N;i++)scanf("&f",&score[i]);av=aver(p);printf("这5个学生的平均成绩是%5.2f",av);}形参用数组实参用指针方法二:实参用数组名,形参用指针变量。#defineN5floataver(float*pa)

{inti;floatav,s=0;for(i=0;i<N;i++)s+=*pa++;av=s/N;return(av);}voidmain(){floatscore[N],av;inti;printf("请输入5个学生的成绩!");for(i=0;i<N;i++)scanf("&f",&score[i]);av=aver(score);

printf("这5个学生的平均成绩是%5.2f",av);}形参用指针实参用数组方法三:实参用指针变量,形参也用指针变量。#defineN5floataver(float*pa){inti;floatav,s=0;for(i=0;i<N;i++)

s+=*pa++;av=s/N;return(av);}voidmain(){floatscore[N],av,*p=score;

inti;printf("!");for(i=0;i<N;i++)

scanf("&f",&score[i]);av=aver(p);

printf("%5.2f",av);}以上几种方法,实质上都是地址的传递,方法一的形参是数组名,方法二和方法三的形参是指针变量,由于数组名代表数组的首地址,所以实现的效果是一样的。形参用指针实参用指针#defineN5voidmain(){inta[N],*p;intcount=0,sum=0;printf("%d!",N);for(p=a;p<a+N;p++){scanf("%d",p);if(*p>0){sum+=*p;count++;}}p=a;while(p<a+N)

printf("%-3d",*p++);printf("\n");

printf("count=%d\n",count);

printf("sum=%d\n",sum);

return0;}【例9.4】输入n个数,对其中的正数统计个数并求和,程序最后输出原始数据和统计结果。将【例8.8】冒泡法排序的程序通过指针的方法修改如下:#include"stdio.h"#defineM5voidsort(intv[],intn){inti,j,temp;for(i=0;i<n;i++){for(j=n-1;j>i;j--){if(v[j-1]>v[j]){temp=v[j-1];v[j-1]=v[j];

v[j]=temp;}}}return0;}voidprint(intv[],intn)

{inti;for(i=0;i<n;i++)

{printf("%d",v[i]);}printf("\n");return0;}main(){inti,a[M];for(i=0;i<M;i++)

{scanf("%d",&a[i]);}sort(a,M);

print(a,M);return0;}【例9.5】用选择法对数组元素按照从大到小的顺序排序voidmain(){voidsort(intx[],intn);int*p,i,a[10];p=a;for(i=0;i<10;i++)scanf("%d",p++);p=a;sort(p,10);for(p=a,i=0;i<10;i++){printf("%d",*p);p++;}return0;}voidsort(intx[],intn){inti,j,k,t;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++)if(x[j]>x[k])k=j;if(k!=i){t=x[i];x[i]=x[k];x[k]=t;}}return0;}voidsort(int*x,intn){inti,j,k,t;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++)if(*(x+i)>*(x+k))k=j;if(k!=i){t=*(x+i);*(x+i)=*(x+k);*(x+k)=t;}}return0;}二维数组逻辑结构inta[3][4];它的逻辑存储结构指针与二维数组

a[i]*(*(

a[i]+j)*(a+i)+j)[j]等价二维数组的物理存储inta[3][4];,*p=ap就是p[0]

p+1就是p[1]p+i就是p[i]二维数组的指针变量

类型标识符(*指针变量名)[长度];二维数组的列数int(*p)[4];表示变量是指针类型小括号不能掉,缺省的为指针数组指针与二维数组的应用举例【例9.6】用指向数组元素的指针变量输出数组元素的值,并统计其中的正数。main(){inta[][4]={{1,-2,3,4},{11,-22,33,44},{-55,66,0,-89}};intcount=0,*p;for(p=a[0];p<a[0]+12;p++){if(*p>0)count++;printf("%4d",*p);}printf("\ncount=%d\n",count);}用普通的指针变量来访问二维数组的元素【例9.7】有一个班,3个学生,每个学生有4门课程,计算总平均分以及第n个学生的成绩。用指向二维数组的指针变量访问数组元素search(float(*p)[4],intn){inti;for(i=0;i<4;i++)printf("%6.2f",*(*(p+n)+i));printf("\n");}思考:怎样查找第m个学生第n门课程的成绩?main(){intn;floatscore[3][4]={{65,67,70,60},{80,87,90,81},{90,99,100,98}};scanf("%d",&n);average(*score,12);search(score,n);}average(float*p,intn){float*qq;floatsum=0,aver;qq=p+n+1;for(;p<=qq;p++)sum+=*p;aver=sum/n;printf("Average=%5.2f\n",aver);}9.3字符串与指针9.3.1字符串的表示形式在C语言中,可以用两种方法访问一个字符串。(1)用字符数组存放一个字符串,然后输出该字符串。把字符串的各字符(包括结束标志'\0')依次保存在字符数组中,利用下标变量或数组名对数组进行操作。输出时用"%s"格式进行整体输出。【例9.8】定义一个字符串,对它初始化,然后输出该字符串。#include"stdio.h"voidmain(){charstr[]="Cprogram.";printf("%s\n",str);return0;}(2)用字符指针指向一个字符串也可以直接定义指向字符串的指针变量,利用该指针变量对字符串进行操作。【例9.9】字符指针应用举例。#include"stdio.h"voidmain(){char*str="Cprogram.";printf("%s\n",str);return0;}对字符串中字符的存取,既可以使用下标的方法,也可以使用指针的方法【例9.10】将字符串a复制给字符串bmain(){chara[]="Iamaboy.",b[20];inti;for(i=0;*(a+i)!='\0';i++)*(b+i)=*(a+i);*(b+i)='\0';printf("stringais:%s\n",a);printf("stringbis:");for(i=0;b[i]!='\0';i++)printf("%c",b[i]);printf("\n");return0;}也可以使用指针变量,通过改变指针变量的指向,来处理所指向的内容

【例9.11】用指针变量来处理【例9.10】的问题。main(){chara[]="Iamaboy.",b[20],*p1,*p2;inti;p1=a;p2=b;for(;*p1!='\0';p1++,p2++)*p2=*p1;*p2='\0';printf("stringais:%s\n",a);printf("stringbis:");for(i=0;b[i]!='\0';i++)printf("%c",b[i]);printf("\n");}使用时应注意以下几个问题:

①字符串指针变量本身是一个变量,用于存放字符串的首地址。②对字符数组作初始化赋值,必须采用外部类型或静态类型,而对字符串指针变量则无此限制。例如:staticcharst[]={"CLanguage"};char*ps="CLanguage";③对字符串指针方式可以写为:char*ps;*ps="CLanguage";而对数组方式:staticcharst[]={"CLanguage"};char*ps="CLanguage";不能写成:staticcharst[20];st[]={"CLanguage"};9.3.2字符指针作为函数的参数将一个字符串从一个函数传递到另一个函数,一方面可以用字符数组名做参数,另一方面可以用指向字符串的指针变量做参数,这样,在被调函数中若改变了字符串的内容,则主调函数中相应的字符串的内容也随之改变。【例9.12】用函数的调用实现字符串的复制

(1)用字符数组名作为参数main(){copy_string(charform[],charto[]);chara[]="Iamateacher.";charb[]="Youareastudent.";printf("strinta:%s\nstringb:%s\n",a,b);printf("copystringa,to,stringb:\n");copy_string(a,b);printf("strinta:%s\nstringb:%s\n",a,b);return0;}copy_string(charform[],charto[]){inti=0;while(form[i]!='\0'){to[i]=form[i];i++;}to[i]='\0';}在main函数中也可以用字符指针变量作为实参,先使指针变量a和b分别指向两个字符串。main函数可以做如下修改:

voidmain(){voidcopy_string(charform[],charto[]);charp[]="Iamateacher.";charq[]="Youareastudent.";char*a=p,*b=q;printf("strinta:%s\nstringb:%s\n",a,b);printf("copystringa,to,stringb:\n");copy_string(a,b);printf("strinta:%s\nstringb:%s\n",a,b);return0;}voidmain(){voidcopy_string(char*form,char*to);charp[]="Iamateacher.";charq[]="Youareastudent.";char*a=p,*b=q;printf("strinta:%s\nstringb:%s\n",a,b);printf("copystringa,to,stringb:\n");copy_string(a,b);printf("strinta:%s\nstringb:%s\n",a,b);return0;}(2)形参用字符指针变量

voidcopy_string(char*form,char*to){for(;*form!='\0';form++,to++){*to=*form;}*to='\0';return0;}int*pb[2]pb[0]pb[1]intb[2][3]123246指针数组用途:用于处理二维数组或多个字符串指针数组定义形式:

[存储类型]数据类型*数组名[数组长度];指针本身的存储类型指针所指向变量的数据类型例int*p[4];指针数组赋值与初始化赋值:main(){intb[2][3],*p[2];

p[0]=b[0];p[1]=b[1];……..}初始化:main(){intb[2][3],*p[]={b[0],b[1]};……..}赋值:main(){chara[]="Fortran";charb[]="Lisp";charc[]="Basic";

char*p[4];

p[0]=a;p[1]=b;p[2]=c;p[3]=NULL;……..}指针数组赋值与初始化或:main(){char*p[4];p[0]="Fortran";p[1]="Lisp";p[2]="Basic";p[3]=NULL;……..}Lisp\0Fortran\0Basic\0p[0]p[1]p[2]p[3]0指针数组赋值与初始化初始化:main(){char*p[]={"Fortran","Lisp","Basic",NULL};……..}0

charname[5][9]={"gain","much","stronger","point","bye"};

char*name[5]={"gain","much","stronger","point","bye"};gain\0stronger\0point\0much\0name[0]name[1]name[2]name[3]name[4]bye\0gain\0stronger\0point\0much\0bye\0二维数组存储空间固定字符指针数组相当于可变列长的二维数组指针数组元素的作用相当于二维数组的行名但指针数组中元素是指针变量二维数组的行名是地址常量二维数组与指针数组区别:main(){intb[2][3],*p[2];inti,j;for(i=0;i<2;i++)for(j=0;j<3;j++) b[i][j]=(i+1)*(j+1);

p[0]=b[0];p[1]=b[1];for(i=0;i<2;i++)for(j=0;j<3;j++)printf("b[%d][%d]:%2d\n",i,j,*(p[i]+j));}例用指针数组处理二维数组int*p[2]p[0]p[1]intb[2][3]b[0][0]*(p[0]+0)b[0][1]*(p[0]+1)b[0][2]*(p[0]+2)b[1][0]*p([1]+0)b[1][1]*(p[1]+1)b[1][2]*(p[1]+2)123246b[0][0]:1b[0][1]:2b[0][2]:3b[1][0]:2b[1][1]:4b[1][2]:6例对字符串排序(简单选择排序)main(){voidsort(char*name[],intn),print(char*name[],intn);char*name[]={"Followme","BASIC","GreatWall","FORTRAN","Computer"};intn=5;sort(name,n);

print(name,n);}voidsort(char*name[],intn){char*temp;inti,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0)k=j;if(k!=i){temp=name[i];name[i]=name[k];name[k]=temp;}}}name[0]name[1]name[2]name[3]name[4]nameGreatWallFORTRANComputerFollowmeBASICkjkjjji=0strcmp(name[k],name[j])

比较规则:两个字符串自左向右逐个字符比较(按ASCII值大小比较),直到出现不同的字符或遇到'\0'为止。如果全部字符相同,认为两个字符串相等;若出现不相同的字符,则以第一个不相同的字符的比较结果为准。(1)如果字符串1=字符串2,则函数返回值为0。(2)如果字符串1>字符串2,则函数返回值为一正整数。(3)如果字符串1<字符串2,则函数返回值为一负整数。main(){voidsort(char*name[],intn),print(char*name[],intn);char*name[]={"Followme","BASIC","GreatWall","FORTRAN","Computer"};intn=5;sort(name,n);

print(name,n);}voidsort(char*name[],intn){char*temp;inti,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0)k=j;if(k!=i){temp=name[i];name[i]=name[k];name[k]=temp;}}}i=1name[0]name[1]name[2]name[3]name[4]nameGreatWallFORTRANComputerFollowmeBASICkjjjkkmain(){voidsort(char*name[],intn),print(char*name[],intn);char*name[]={"Followme","BASIC","GreatWall","FORTRAN","Computer"};intn=5;sort(name,n);

print(name,n);}voidsort(char*name[],intn){char*temp;inti,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0)k=j;if(k!=i){temp=name[i];name[i]=name[k];name[k]=temp;}}}i=2name[0]name[1]name[2]name[3]name[4]nameGreatWallFORTRANComputerFollowmeBASICkjjkmain(){voidsort(char*name[],intn),print(char*name[],intn);char*name[]={"Followme","BASIC","GreatWall","FORTRAN","Computer"};intn=5;sort(name,n);

print(name,n);}voidsort(char*name[],intn){char*temp;inti,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0)k=j;if(k!=i){temp=name[i];name[i]=name[k];name[k]=temp;}}}i=3name[0]name[1]name[2]name[3]name[4]nameGreatWallFORTRANComputerFollowmeBASICjkmain(){voidsort(char*name[],intn),print(char*name[],intn);char*name[]={"Followme","BASIC","GreatWall","FORTRAN","Computer"};intn=5;sort(name,n);

print(name,n);}voidsort(char*name[],intn){char*temp;inti,j,k;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0)k=j;if(k!=i){temp=name[i];name[i]=name[k];name[k]=temp;}}}name[0]name[1]name[2]name[3]name[4]nameGreatWallFORTRANComputerFollowmeBASICmax…...指令1指令2函数返回值的数据类型专门存放函数入口地址可指向返回值类型相同的不同函数函数指针变量指向的函数必须有函数说明()不能省int(*p)()与int*p()不同指向函数的指针函数指针:函数在编译时被分配的入口地址,用函数名表示指向函数的指针变量定义形式:

数据类型

(*指针变量名)();

如int(*p)();函数指针变量赋值:如p=max;函数调用形式:

c=max(a,b);

c=(*p)(a,b);

c=p(a,b);对函数指针变量p

n,p++,p--无意义例用函数指针变量调用函数,两个数较大的数main(){intmax(int,int);inta,b,c;scanf("%d,%d",&a,&b);

c=max(a,b);printf("a=%d,b=%d,max=%d\n",a,b,c);}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}main(){intmax(int,int),(*p)();inta,b,c;

p=max;scanf("%d,%d",&a,&b);c=(*p)(a,b);printf("a=%d,b=%d,max=%d\n",a,b,c}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}例用函数指针变量作参数,求最大值、最小值和两数之和main(){inta,b,max(int,int);intmin(int,int),add(int,int);voidprocess(int,int,int(*fun)());scanf("%d,%d",&a,&b);process(a,b,max);process(a,b,min);process(a,b,add);}voidprocess(intx,inty,int(*fun)()){intresult;result=(*fun)(x,y);printf("%d\n",result);}max(intx,inty){printf(“max=”);return(x>y?x:y);}min(intx,inty){pri

温馨提示

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

评论

0/150

提交评论