程序各章课件_第1页
程序各章课件_第2页
程序各章课件_第3页
程序各章课件_第4页
程序各章课件_第5页
已阅读5页,还剩63页未读 继续免费阅读

付费下载

下载本文档

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

文档简介

第七章指针【教学要求】1.深刻理解并掌握指针的概念。2.掌握指针变量的定义和应用,指针变量作为函数参数的用法。3.掌握指向数组的指针与指向数组的指针变量的概念、定义和应用。4.掌握指向字符串的指针的定义和应用。5.理解指向函数的指针的定义和用法。6.了解返回指针值的函数的定义和应用,了解它与指向函数的指针变量的区别。7.了解指针数组的定义和应用,掌握指针的指针的定义和应用,了解它指针数组与指向数组的指针变量的区别。【教学要点】一、基础知识(重点)二、指针变量的引用(重点)三、数组的指针和指向数组的指针变量(难点)四、字符串的指针和指向字符串的指针变量(难点)五、函数的指针和指向函数的指针变量六、返回指针值的函数七、指针数组与指向指针的指针八、有关指针的数据类型和指针运算小结第七章指针基础知识为什么要定义变量?意味着在编译时,为变量分配适当大小的内存单元。对存储单元的理解:地址:给定的一个内存单元的编号(字节偏移量)。内容:某一个内存单元中存放的数据就是这个内存单元的内容。这些数据根据定义的变量的类型的不相同,占用内存的大小不同.(变量的值)变量、地址、变量值之间的关系CPU访问内存中数据的方式9......7896...555222789变量名为k单元地址为2000如:intk=789;2000H2002H2008H2004H地址变量3变量4变量2变量1假定都为整型变量内存单元地址内容CPU访问内存中数据的方式CPU对变量的访问是根据内存单元的地址来进行的。访问的方式有:(1)直接访问含义:已知变量的地址直接取地址单元内的值。方法:通过变量名进行访问。如:intx=2;printf(“%d”,x);(2)间接访问含义:通过存放变量地址的变量(指针变量)来访问目标单元的值。方法:通过指针变量进行访问。引入了指针的概念:指针的概念1、指针的含义:指针即变量的地址。(如2000H、2001H…2009H等)2、指针变量:含义:用于存放指针(地址)的变量。定义方法:数据类型*变量名如:intx=3;

int*pointer1;

pointer1=&x;3、要点:&x(2000H)3pointer1*pointer1x2000H数据类型*变量名1、数据类型:指针变量所指向目标单元的值的类型。2、*:指针变量的定义符3、变量名:目标变量在内存中的位置(表示一个地址)如:pointer1=&x;4、指针变量的初始化:将指针变量指向一个具体的变量。如:intx=3;floaty;charz;int*pointer1=&x;float*pointer2=&y;char*pointer3=&z;2000H3pointer1*pointer1x2000H指针变量的引用指针运算符:&和*的用法指针的运算:算术、关系、赋值。指针变量作为函数的参数1、&:取地址运算符作用:用于变量名之前,表示该变量的存储地址。2、*:指针运算符作用:用于指针变量名之前,获取该指针所指目标单元的值。例如:#include<stdio.h>main(){inta,b,*point1,*point2;a=100,b=200;point1=&a,point2=&b;printf(“%d,%d\n”,a,*point2);}3、&和*两个运算符的优先级别是相同的,结合规律是右结合性:如:若point1=&a;则&*point1等价于&a;*&a

等价于

a;(*point1)++等价于a++;指针运算符指针的运算1、算术运算含义:对于地址的运算,只能进行整型数据的加、减运算。规则:指针变量+n

意味着将指针指向的当前变量向前或后的第n个变量单元。如:2、关系运算作用:用于识别目标变量在内存中的前后位置。用法:inti,j;int*p1=&i,*p2=&j;

p1>p2用于识别变量i,j在内存的排列顺序。3、赋值运算作用:对指针变量的赋值运算,将改变指针变量的指向如:4、举例:ijp1p210001002200020022004地址kjip=&iinti,j,k;int*p=&i;(p=2000)p++;(p=2002)p++;(p=2004)p--;(p=2002)小结:指针变量的算术运算结果是改变指针目标的指向;指针变量算术运算的过程:p新=p原值+n*sizeof(类型)提供指针的目的:使访问者与访问对象相隔离改进对成批数据的访问速度20002002地址jip=&i例:inti=1,j=2;int*p;p=&i;*p=10;printf(“%d”,*p);p=&j;printf(“%d”,*p);要点:应随时了解指针变量的目标指向。不允许直接对指针变量赋常量值。如:int*point;point=1000;()3.只能给指针变量一个具有地址属性的值(数据或变量)。例exp7_1:分析下面程序的功能.#include<stdio.h>main(){int*p1,*p2,*p,a,b;scanf(“%d,%d”,&a,&b);p1=&a,p2=&b;if(a<b){p=p1;p1=p2;p2=p;}printf(“a=%d,b=%d\n”,a,b);printf(“max=%d,min=%d\n”,*p1,*p2);}&a7&b8p2p1&b7&a8p2p1abbap&a指针变量作为函数参数1、含义:函数的参数不仅可以是基本数据类型,还可以是指针类型。2、功能:将一个变量的地址传送到另一个函数中。3、例exp7_2:分析下面的例子#include<stdio.h>main(){inta,b,*point1,*point2;scanf(“%d,%d”,&a,&b);point1=&a,point2=&b;

if(a<b)swap(point1,point2);printf(“\n%d,%d\n”,a,b);}结论:intswap(p1,p2)int*p1,*p2;{intp;p=*p1;*p1=*p2;*p2=p;}1、指针变量作为参数,从调用函数到被调用函数传递的不是一个变量而是变量的地址;2、指针变量作为函数的参数,从实参到形参的数据传递仍然遵循“单向值传递”的原则,只是此时传递的是地址。3、通过函数的调用可以得到n个需改变变量值的方法:用指针变量;用数组名;用全局变量;4、例:例exp7_3:分析下面程序的执行情况:#include<stdio.h>voidswap(p1,p2)int*p1,*p2;{int*p;

*p=*p1;*p1=*p2;*p2=*p;}intmain(){inta,b;scanf(“%d,%d”,&a,&b);if(a<b)swap(&a,&b);printf(“\n%d,%d\n”,a,b);return0;}有问题例exp7_4:分析下面的程序并写出结果。#include<stdio.h>voidswap(int*a,int*b){int*t;t=a,a=b,b=t;printf(“%d,%d\n”,*a,*b);}intmain(){inta=3,b=5;swap(&a,&b);printf(“%d,%d\n”,a,b);return0;}运行结果为:5,3 3,5例exp7_5:分析下面的程序写出结果#include<stdio.h>voidswap(inta,intb){intt;t=a,a=b,b=t;printf(“%d,%d\n”,a,b);}intmain(){inta=3,b=5;swap(a,b);printf(“%d,%d\n”,a,b);return0;}运行结果:5,33,5例exp7_6:分析下面的程序写出结果#include<stdio.h>voidswap(int*a,int*b){intt;t=*a,*a=*b,*b=t;printf(“%d,%d\n”,*a,*b);}intmain(){inta=3,b=5;swap(&a,&b);printf(“%d,%d\n”,a,b);return0;}运行结果:5,35,3例exp7_7:输入a、b、c三个整数,按大小顺序输出。#include<stdio.h>voidswap(int*a,int*b){intt;t=*a,*a=*b,*b=t;}intmain(){inta,b,c,*p1,*p2,*p3;scanf(“%d,%d,%d”,&a,&b,&c);p1=&a,p2=&b,p3=&c;exchange(p1,p2,p3);printf(“%d,%d,%d\n”,a,b,c);return0;}voidexchange(q1,q2,q3)int*q1,*q2,*q3;{if(*q1<*q2)swap(q1,q2);if(*q1<*q3)swap(q1,q3);if(*q2<*q3)swap(q2,q3);}运行情况:输入:9,0,10输出:10,9,0数组的指针和

指向数组的指针变量概念(数组的指针、数组元素的指针、指向数组的指针变量)定义方法利用指针访问数组的几种方法数组名作为函数参数与指针的使用指向二维数组的指针和指针变量1、数组的指针:数组的起始地址(即数组名)。是一个恒定值指针。2、数组元素的指针:数组元素的地址。3、指向数组的指针变量:用于存放数组的起始地址或某一数组元素地址的变量。基本概念定义方法一、定义方法:与一般指针变量的定义方法相同。如:inta[10],*p1,*p2;p1=a;p2=&a[2];注:p1为指向数组的指针

p2为指向数组元素的指针二、要点:在定义指针变量时可以直接赋初值。如:inta[10],*p1=a,*p2=&a[0];a[0]aa[1]a[2]a[9]p1=aa[i]p2利用指针访问数组的几种方法一、功能:引用数组元素可以用下标法,还可以用指针法。使用指针方法能使目标程序的质量占内存少、运行速度快。二、基本方法1、将指针指向数组中的某个元素;2、利用*(p+n)获得数组元素的值。如:inta[9]={0,1,2,3};int*p=a;printf(“%d”,*p);printf(“%d”,*p++);printf(“%d”,*p--);3、例:三、要点:a[0]*(p+n-1)aa[1]a[2]a[n-1]p++p++p=aa[i]p+i或a+ip+n-1*(p+i)或p[i]例exp7_8:输出数组的全部元素。方法一:下标法#include<stdio.h>intmain(){inta[10];inti;for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(i=0;i<10;i++)printf(“%d,”,a[i]);return0;}方法二:地址法#include<stdio.h>intmain(){inta[10];inti;for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(i=0;i<10;i++)printf(“%d,”,*(a+i));return0;}例exp7_8:输出数组的全部元素。方法三:指针法#include<stdio.h>intmain(){inta[10];int*p,i;for(i=0;i<10;i++)scanf(“%d”,&a[i]);printf(“\n”);for(p=a;p<a+10;p++)printf(“%d,”,*p);return0;}三种方法的比较:方法1与方法2的执行效率相同,都是先计算数组元素的地址,再访问数组元素的值,费时。方法3利用指针变量直接访问数组元素的值,不必计算数组元素的地址,故执行效率高。下标法直观,指针法与地址法不够直观。例exp7_9:下面的程序的输出结果是什么?#include<stdio.h>inta[]={2,4,6,8};main(){inti,b[4],*p=a;for(i=0;i<4;i++)b[i]=*p++;printf(“%d\n”,b[2]);}运行结果为:6要点:1、指针变量可以实现自身值的改变:如:p++;但数组名则不能进行改变:a++是错误的用法。2、应注意指针变量的当前值。例:3、指针变量可以指向数组以后的内存单元。4、注意以下的指针运算:若:inta[10],*p=a;则:(1)p++

等价于&a[1]

(2)*p++

等价于*(p++)

但*(p++)与*(++p)却不同(3)(*p)++

等价于a[0]++例exp7_10:下面的程序的输出结果是什么?#include<stdio.h>intmain(){inta[10];int*p,i;p=a;for(i=0;i<10;i++)scanf(“%d”,p++);printf(“\n”);for(i=0;i<10;i++,p++)printf(“%d,”,*p);return0;}数组名作函数的参数一.数组元素作函数的参数。二.数组名作为函数的参数:实参与形参操作的是内存中的同一段地址单元,这样在被调用函数中对数组元素的内容的改变将会反映到调用函数中.(即地址传递或双向传递)三.数组作函数的参数时,实参与形参还可用指针的形式给出:(同样是地址传递)用数组名与数组的指针组合形式可以是:四、举例:实参数组名数组名指针指针形参数组名指针数组名指针例exp7_11:将数组a中的n个整数按相反的顺序存放。#include<stdio.h>voidinv(int*x,intn){int*p,m,t,*i,*j;m=(n-1)/2;

i=x;j=x+n-1;p=x+m;for(;i<=p;i++,j--){t=*i;*i=*j;*j=t;}return;}intmain(){staticinta[10]={3,7,9,11,0,6,7,5,4,2};inti,*p,

p=a;inv(p,10);for(p=a;p<a+10;p++)printf(“%d,”,*p);printf(“\n”);return0;}例exp7_12:下面程序的输出结果是:#include<stdio.h>#defineMAX 3inta[MAX];intmain(){fun1();fun2(a);printf(“\n”);return0;}fun1()

{intk,t=0;for(k=0;k<MAX;k++,t++)a[k]=t+t;}fun2(intb[])

{intk;for(k=0;k<MAX;k++)printf(“%d”,*(b+k));}运行结果为:024例exp7_13:分析以下程序的输出结果。#include<stdio.h>floatsort(intdata[],intn){inti,j,t;for(i=0;i<n;i++)for(j=i+1;j<n;j++) if(data[i]<data[j]) {t=data[i];data[i]=data[j];data[j]=t;}}intmain()

{intarray[5]={2,8,7,5,9};inti;sort(array,3);for(i=0;i<5;i++)printf(“%d”,array[i]);printf(“\n”);return0;}运行结果为:87259例exp7_14:分析程序写出结果.#include<stdio.h>

voidfun(int*s){staticintj=0;do{s[j]+=s[j+1];}while(++j<2);}intmain(){intk,a[10]={1,2,3,4,5};for(k=1;k<3;k++)fun(a);for(k=0;k<5;k++)printf(“%d”,a[k]);return0;}运行结果为:35745指向多维数组的指针和指针变量一、多维数组的地址

例:inta[3][4];二、指向二维数组的指针1、指向二维数组元素的指针2、指向二维数组行的指针3、多维数组的指针作函数的参数多维数组的地址a[1]a[2]a[0][0]a[0][1]a[0][2]a[0][3]a[2][0]a[2][1]a[1][1]a[2][2]a[1][2]a[1][3]a[2][3]a[1][0]a[0]aa[0][0]a[0][0]a[0][3]a[1][2]a[1][0]a[1][1]a[2][1]a[1][3]a[2][0]a[2][2]a[2][3]a[0][2]a[0][1]aa[0]a[1]a[2]二维数组的地址:a二维数组行的地址:a[0],a[1],a[2],a+i二维数组元素的地址:&a[0][0],&a[i][j],a[i]+j二维数组元素值:a[i][j],*(a[i]+j),*(*(a+i)+j)小结:

表示形式 含义a 二维数组名,数组首地址a[0],*(a+0),*a 第0行第0列元素的地址a+1 第1行首地址a[1],*(a+1) 第1行第0列元素的地址a[1]+2,*(a+1)+2第1行第2列元素的地址

&a[1][2]*(a[1]+2),第1行第2列元素的值

*(*(a+1)+2),a[1][2]1、含义:一个指针变量可以指向二维数组的元素;而二维数组的元素也可以表示成指针的形式。2、例exp7_15:分析以下的程序。#include<stdio.h>intmain(){staticintaa[3][3]={{2},{4},{6}};inti,*p=&aa[0][0];for(i=0;i<2;i++){if(i==0)aa[i][i]=*p+1;else++p;printf(“%d,”,*p);}return0;} 运行结果为:指向二维数组元素的指针3,0例exp7_16:分析以下的程序。#include<stdio.h>intmain(){staticinta[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};int*p;for(p=a[0];p<a[0]+12;p++){if((p-a[0])%4==0)printf(“\n”);printf(“%4d”,*p);}return0;}1、含义:指针所指的是包含m个元素的一维数组。也即指向二维数组行的指针2、表示方法:数据类型(*指针变量)[数组元素个数]3、引用方法:例exp7_17:分析以下的程序#include<stdio.h>main()

{staticinta[3][4]={1,3,4,7,9,,11,13,15,17,19,21,23};int(*p)[4]=a,i,j,k=0;for(i=0;i<3;i++)for(j=0;j<2;j++)k=k+*(*(p+i)+j);printf(“%d\n”,k);}指向二维数组行的指针a[0][0]a[0][3]a[1][2]a[1][0]a[1][1]a[2][1]a[1][3]a[2][0]a[2][2]a[2][3]a[0][2]a[0][1]p,aa[0]a[2]p+1p+2a[1]对*(*(p+i)+j)的理解:p+i 相当于a数组的第i行的首地址;*(p+i) 相当于a数组的第i行第0个元素的地址;

等价于a[i];*(p+i)+j 相当于a数组第i行第j列的元素的地址;

等价于&a[i][j]

等价于p[i]+j

等价于a[i]+j*(*(p+i)+j)等价于a[i][j]例exp7_18:分析以下的程序#include<stdio.h>main()

{inta[2][3],(*p)[3];intk=0,j;p=a;for(;k<2;k++)for(j=0;j<3;j++)

*(p[k]+j)=(k+1)*(j+1);printf(“%d\n”,*(p[1]+2));}运行结果为:61.二维数组名作数组的参数:例exp7_19:分析以下的程序#include<stdio.h>intfun(int*p){inti,j;for(i=0;i<3;i++)for(j=0;j<4;j++)*p++=i+j;}main()

{inta[3][4]={1,2};fun(a);printf(“%d\n”,a[2][3]);}运行结果为:二维数组的指针作函数的参数52.指向二维数组的行指针作函数的参数例exp7_20:分析以下的程序#include<stdio.h>fun(int(*p)[3],inti){intk=0,j;for(;k<i;k++)for(j=0;j<3;j++)*(p[k]+j)=(k+1)*(j+1);}main()

{inta[2][3],(*p)[3];p=a;fun(p,2);printf(“%d\n”,*(p[1]+2));}运行结果为:6字符串的指针和

指向字符串的指针变量字符串的表示方法:字符数组与字符串指针字符串指针作函数的参数字符指针变量与字符数组的区别1.用字符数组实现main()

{staticcharstr[]=“Iamastudent.”;puts(str);}说明:str是数组名,代表数组的首地址,str[i]代表数组的第i个元素,str[i]等价于*(str+i).2.用字符指针实现main()

{char*str=“Iamastudent.”;puts(str);}

要点:字符串的表示方法1、字符串指针的作用:可以用来描述一个字符串。方法:char*str=“Iamastudent.”;2、物理含义:不是将字符串的内容赋值给指针变量,而是将其起始地址赋给它。char*str;str=“Iamastudent.”;3、应用:利用字符串的指针变量对字符串进行输入与输出。puts(),gets()scanf(),printf()的%s输出格式。例:字符串指针例exp7_21:分析下面的程序#include<stdio.h>main(){chararr[]=“ABCDE”;char*ptr;for(ptr=arr;ptr<arr+5;ptr++)printf(“%s\n”,ptr);}运行结果为:ABCDEBCDECDEDE

E例exp7_22:有以下的程序,输出结果为:#include<stdio.h>intmain()

{char*p1=“programming”,*p2=“language”;inti;for(i=0;i<7;i++)if(*(p1+i)==*(p2+i))printf(“%c”,*(p1+i));return0;}结果:ga1.用字符数组作函数的参数例exp7_23:分析以下的程序#include<string.h>#include<stdio.h>intmain()

{intfun(chars[]);staticchara[]=“abcdefghi”;intk;fun(a);puts(a);return0;}intfun(chars[]){intx,y;charc;for(x=0,y=strlen(s)-1;x<y;x++,y--){c=s[y];s[y]=s[x];s[x]=c;}}字符串指针作函数的参数运行结果为:ihgfedcba2.用字符指针作函数的参数例exp7_23:分析以下的程序#include<string.h>#include<stdio.h>intmain()

{char*a=“abcdefghi”;intk;fun(a);puts(a);return0;}fun(char*s){intx,y;charc;for(x=0,y=strlen(s)-1;x<y;x++,y--){c=s[y];s[y]=s[x];s[x]=c;}} 1.字符数组由若干个元素组成,每个元素存放一个字符,而字符指针存放的地址(当处理字符串时存放的是字符串的地址);2.赋初值方式不同; staticchara[]=“Iamastudent.”; char*str=“IloveChina.”;3.赋值方式不同;1)对于字符数组赋值不能使用以下的方法:charstr[10];str=“book”;2)对于字符类型的指针变量可以使用以下的方法:char*str;str=“Thisisabook.”;字符指针与字符数组的区别4.字符指针变量在使用之前必须初始化,即使其指向一个具体的存储单元。如:charstr[20];scanf(“%s”,str);是正确的而char*str;scanf(“%s”,str);将是十分错误的。5.指向字符类型的指针变量可以用指针的形式表示,也可以用下标的形式表示。

例:例exp7_24:分析以下的程序#include<stdio.h>intmain()

{char*str=“Iamastudent.”;

str=str+7;printf(“%s\n”,str);for(;*str;printf(“%c”,*str++));printf(“\n”);return0;}运行结果:student.student.指针形式例exp7_25:分析以下的程序#include<stdio.h>intmain()

{char*str=“Iamastudent.”;inti;str=str+7;printf(“%s\n”,str);for(i=0;i<7;printf(“%c”,str[i++]));printf(“\n”);return0;}数组形式函数的指针和

指向函数的指针变量一、概念:1、函数的指针:函数在内存中的入口地址(用函数名表示)2、指向函数的指针变量:1)含义:用于存放函数名的变量。2)定义方法:

double(*f)(dlouble),x;f=sin;x=(*f)(30*3.14159/180.0);3)要点:不能将(*f)()写成*f()。二、用指向函数的指针变量作函数参数1、含义:函数名或指向函数的指针作为函数的参数,将函数的入口地址传送给对应的形参指针,使其也指向指定的函数。2、举例:例exp7_26:分析以下的程序#include<string.h>#include<math.h>doubletra(double(*f1)(double),double(*f2)(double),doubley){return((*f1)(y)/(*f2)(y));}intmain(){doubleyt,yc;yt=tra(sin,cos,60*3.1415/180.0);yc=tra(cos,sin,60*3.1415/180.0);printf(“%f,%f\n”,yt,yc);return0;}运行结果为:1.731927,0.577391返回指针值的函数一、含义:函数的返回值类型可以是基本数据类型,也可以是指针,即一个地址。二、定义方法与使用要点1、方法:类型标识符*函数名(参数表)如:int*a(intx,inty)

将返回一个指向整型数据的指针。2、要点:请区分:int*a(intx,inty);

与int(*a)(intx,inty)的不同含义。三、应用举例例exp7_27:有三个学生,每位学生有4门成绩,要求用户在输入学生序号后,能输出该学生的全部成绩。#include<stdio.h>intmain(){staticfloatscore[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};float*search(float(*pointer)[4],intn);float*p;inti,m;scanf(“%d”,&m);p=search(score,m);for(i=0;i<4;i++)printf(“%5.2f\t”,*(p+i));return0;}

float*search(pointer,n)float(*pointer)[4];intn;{float*pt;pt=*(pointer+n);return(pt);}指针数组与指向指针的指针一、指针数组1、概念:数组元素均为指针类型数据的数组。2、定义方法:类型标识符*数组名[数组长度]

如:int*p[4];3、要点:请区别int*p[4]与int(*p)[4]的不同。举例:二、指向指针的指针1、含义:用于存放指针变量地址的变量。2、定义方式:inti,*p,**q;3、应用举例:三、指针数组作main()的形参例exp7_28:将若干个字符串按字母顺序由小到大输出。#include<stdio.h>#include<string.h>intmain(){voidsort(char*name[],intn);voidprint(char*name[],intn);staticchar*name[]={“Followme”,”BASIC”,

“GreatWall”,”FORTRAN”,”Computerdesign”};

温馨提示

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

评论

0/150

提交评论