C语言 第8章 指针课件.ppt

C语言 第8章 指针课件.ppt

ID:57056845

大小:758.50 KB

页数:96页

时间:2020-07-30

上传者:U-5649
C语言 第8章 指针课件.ppt_第1页
C语言 第8章 指针课件.ppt_第2页
C语言 第8章 指针课件.ppt_第3页
C语言 第8章 指针课件.ppt_第4页
C语言 第8章 指针课件.ppt_第5页
资源描述:

《C语言 第8章 指针课件.ppt》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库

第8章指针何平何平2020/7/251 8.1变量的地址和指针8.2指针变量的定义及引用8.3指针与函数8.4指针与数组8.5字符指针8.6用指针处理链表重点:1:指针的概念、指针变量的定义和引用;2:如何用指针访问变量、一维数组、处理字符串以及指针作为函数参数的作用,如何实现数据的动态存储。内容: 数据在内存中的存储访问变量的方式指针变量8.1变量的地址和指针 在程序中所定义的变量,编译系统会根据变量的类型,分配一定长度的存储空间。内存中每一个存储单元的有唯一编号。如:在turboC中inta=6;/*2个字节*/floatb=5.3;/*4个字节*/2000H2002H2006H65.3ab数据在内存中的存储变量a的指针。记为:&a ●直接访问方式按变量的地址存取变量的值。访问变量的方式例如:printf("%f",b);/*通过变量名b的地址(2002或&b)来输出变量b的值。*/ ●间接访问方式按变量的地址的地址存取变量的值。访问变量的方式(续)例如:用变量pa来存放变量a的地址&a。此时,如果要得到a的值,可以先访问变量pa,得到pa的值为2000(变量a的地址),再通过地址2000找到所指存储单元中的值(a的值),见图。2000H6a(2000H)2000Hpa(1000H)1000H ●变量的指针一个变量的地址称为该变量的指针。如地址2000H是变量a的指针。可记为:&变量名●指针变量如果有一个变量专门用来存放另一个对象的地址(即指针),称为指针变量。如pa是一个指针变量,pa中的值为指针。指针变量 指针变量的定义指针变量的引用8.2指针变量的定义及引用 数据类型说明符*标识符;例如:int*pt;指针变量的定义指针变量所指向的变量的类型。变量名指针标记表明其后的变量是指针变量 ●说明指针变量可以指向任何类型的对象。指针变量必须先定义,后使用,并且必须先赋值后引用。指针变量的定义(续) 示例:inta,b;int*p1,*p2;p1=&a;p2=&b;p1p2ab&a&bint*p1=&a,*p2=&b; 在定义了一个指针变量后,可以对该指针变量进行各种操作,操作时用到两个有关指针的运算符.C&:取变量地址运算符*:“指向”运算符或称“间接访问”运算符指针变量的引用示例:&a为变量a的地址。*p为指针变量p所指向的变量的值。若有如下定义:inta,*p=&a;则:*p等价于a #includevoidmain(){inta,*pi;floatf,*pf;charst,*pc;pi=&a;pf=&f;pc=&st;*pi=10;*pf=1.5;*pc=’a’;printf(“%d,%f,%c ”,a,f,st);printf(“%d,%f,%c ”,*pi,*pf,*pc);}单击鼠标,演示程序的执行过程:例6.1pipfpcafst&a&f&st‘a’1.510 #includevoidmain(){inta,b,*p,*p1,*p2;a=3;b=6;p1=&a;p2=&b;p=p1;p1=p2;p2=p;printf("%d%d ",*p1,*p2);printf("%d%d ",a,b);}单击鼠标,演示程序的执行过程:p1p2pab&a&b63&a&b&a例6.2 复习小结:指针的概念变量的指针数组的指针函数的指针指针变量字符串的指针通过指向变量的指针变量引用变量的值定义指针变量赋初值 指针作为函数参数函数返回指针函数指针8.3指针与函数 指针作为函数参数简单变量作函数的参数,在函数调用时是按“值传送”方式传递参数的——单向传递。指针变量存放的是“地址”,作函数的参数,在函数调用时按“值传送”方式传递参数——双向传递。(即:通过“传值”完成“地址”的传递) 示例8.3输出两数中的大者#includevoidmax(int*p1,int*p2){intt;t=*p1;*p1=*p2;*p2=t;}voidmain(){inta,b;int*pa,*pb;printf("输入a和b: ");scanf("%d,%d",&a,&b);pa=&a;pb=&b;if(avoidsub(intx,inty,int*z){*z=y-x;}voidmain(){inta,b,c;sub(9,5,&a);sub(3,a,&b);sub(a,b,&c);printf(“%d,%d,%d ”,a,b,c);}注意:指向变量的指针变量做参数,如何进行参数的传递;结果:-4,-7,-3 练习2:#includevoidf(intx,inty,int*cp,int*dp){*cp=x+y;*dp=x-y;}voidmain(){inta=30,b=50,c,d;f(a,b,&c,&d);printf(“%d,%d ”,c,d);}结果:80,-20 函数返回指针函数的返回值可以是整型的、实型的,也可以返回指针。与一般函数的定义不同之处是:在函数名的前面加了一个‘*’号。这就是能够返回指针的函数。 ●定义形式类型说明符*函数名(参数说明){函数体}示例:int*sub(int*x,intn){int*p;………return(p);}/*函数的返回值为指向整型的指针。*/函数返回指针(续) 例8.4请阅读下列源程序,体会其用法,并写出运行结果(输入6,10)。#includeint*max(int*p1,int*p2){int*r;if(*p1>*p2)r=p1;elser=p2;returnr;}voidmain(){inta,b,*p;printf("输入a和b: ");scanf("%d,%d",&a,&b);p=max(&a,&b);printf("max=%d",*p);} ●一个函数在内存中占一片存储空间。在函数被编译时,被分配给一个入口地址,这个入口地址就称为函数的指针。●用一个指针变量指向函数,然后用指向函数的指针变量代替函数名来调用这个函数。函数指针 形式:类型说明符(*变量名)(参数表);例如:int(*p)(int,int);指向某个函数的指针变量设置:函数指针变量=函数名;例如:p=f;函数的调用形式(*指针变量)(实参表列);例如:(*p)(a,b);注意!与int*p(int,int)的区别?函数指针变量的定义 #includeintmax(intx,inty){intz;z=(x>=y?x:y);return(z);}voidmain(){int(*p)(int,int),a,b,m;p=max;/*为函数指针赋初值*/scanf("%d,%d",&a,&b);m=(*p)(a,b);/*a,b做实参,调用max函数*/printf(" a=%d,b=%d,max=%d ",a,b,m);}m=(*p)(a,b);m=max(a,b);例8.5求a,b中的最大者 #includeintadd(intx,inty){intz;z=x+y;return(z);}intmax(intx,inty){intz;if(x>y)z=x;elsez=y;return(z);}例8.6设一个函数p,在调用它的时候,每次实现不同的功能。(1)求a和b之和。(2)找出a,b中大者。(3)求a,b中小者。intmin(intx,inty){intz;if(x#includevoidf1(inta,intb,double*p1,double*p2){*p1=*p2=-b/(2*a);}voidf2(inta,intb,intd,double*p1,double*p2){*p1=(-b+sqrt(d))/(2*a);*p2=(-b-sqrt(d))/(2*a);} voidf3(inta,intb,intd,double*p1,double*p2){*p1=(-b)/(2*a);*p2=sqrt(-d)/(2*a);}voidmain(){inta,b,c,d;doublex1,x2,p,q;scanf(“%d,%d,%d”,&a,&b,&c);d=b*b-4*a*c;if(d<0){f3(a,b,d,&p,&q);printf(“ x1=%.2f+%.2fi,x2=%.2f-%.2fi”,p,q,p,q);} else{if(d)f2(a,b,d,&x1,&x2);elsef1(a,b,&x1,&x2);printf(“ x1=%.2f,x2=%.2f ”,x1,x2);}}返回 指向数组的指针变量引用数组元素的方法8.4指针与数组 定义inta[5],*p;p=&a[0];/*或p=a;*/说明指针变量的类型必须与数组元素的类型相同;定义指针变量的同时赋予数组的首地址。示例:inta[5],*p=a;指向一维数组的指针变量a[0]a[1]a[2]a[3]a[4]p&a[0] 引用数组元素的方法示例:inta[5],i,*p=a;●下标法:用a[i]来引用数组a的第i个数组元素。●指针法(通过指针变量引用数组元素):用*(a+i),*(p+i)引用数组的第i个数组元素。a[0]a[1]a[2]a[3]a[4]p&a[0] for(p=a;p<(a+10);p++)printf("%d",*p);例8.6数组元素的引用#includevoidmain(){inta[10],i;for(i=0;i<10;i++)a[i]=i;for(i=0;i<10;i++)printf("%d",a[i]);}*(a+i)int*p;for(p=a,i=0;i<10;i++,p++)*p=i; ●指向数组元素的指针变量的运算p+1/*指向数组的下一个元素,而不是p值加1*/p++;++p;/*使p指向当前数组元素的后一个元素*/p--;--P;/*使p指向当前数组元素的前一个元素*/p+i;/*往后移i个元素*/p-i;/*往前移i个元素*/p-q;/*求指针变量p和q之间元素的个数,且q在p前*/p+q/*两个地址相加,无意义*/注意:若a是数组名,p是指向a数组的指针变量,则a++是非法的,但p++是合法的且经常使用,用于指向数组下一个元素的地址。 例8.7阅读下列源程序,试说明其功能。#includevoidmain(){intadd(int*p,intn);inta[8]={1,2,3,4,5,6,7,8};int*p,sum;p=&a[0];sum=add(p,8);printf(“sum=%d ”,sum);}intadd(int*p1,intn){inti,total=0;for(i=0;ip*(++p)//先执行p+1—>p,再执行*p(*p)++//先执行*p,再执行*p的值加1,p值不变#includevoidmain(){inta[10]={0,10,20,30,40,50,60},*p=a;printf(“%dt”,*p++);printf(“%dt”,*p);printf(“%dt”,*(++p));printf(“%dt”,(*p)--);printf(“%d ”,*p);}结果:010202019 1:设p1和p2是指向同一个int型一维数组的指针变量,k为int型变量,则不能正确执行的语句是———A)k=*p1+*p2;B)p2=k;C)p1=p2;D)k=*p1*(*p2);练习 2:设有如下定义:inta[]={6,7,8,9,10};int*pt;则下列程序段的输出结果为_________pt=a;*(pt+2)+=2;printf(“%d,%d ”,*pt,*(pt+2));练习结果:6,10 指向函数的指针变量调用函数复习小结:指针的应用指向变量的指针变量引用变量的值指针变量做参数如何进行参数传递指向数组的指针变量引用数组元素 字符串的表示形式程序设计举例8.5字符指针 用字符数组实现如:chars[]=“VC++6.0”;用字符指针实现如:char*ps=“VC++6.0”;或char*ps;ps=“VC++6.0”;字符串的表示形式注意:区分字符指针变量和字符数组名的不同。 #includevoidmain(){char*s1=“VC++6.0";s1+=2;printf("%s ",s1);}例8.9利用字符指针变量输出字符串中部分字符。运行结果++6.0 #includevoidmain(){chara[20],b[20],*p1,*p2;gets(a);p1=a;p2=b;for(;*p1!='';p1++,p2++)*p2=*p1;*p2='';printf("stringais:%s ",a);printf("stringbis:%s ",b);}例8.10将字符串a复制到字符数组b中。a[0]b[0]a[0]P1P2P1P2P1P2strcpy(p2,p1); 例8.11读程序,写结果并总结其功能.如:输入abccbadc c输出?#includevoidmain(){voiddel_ch(char*p,charc);chars[80],*pt=s,ch;printf("请输入一个字符串: ");gets(s);printf("请输入要被删除的字符: ");scanf(“%c”,&ch);del_ch(pt,ch);printf("新的字符串为: %s ",s);}voiddel_ch(char*p,chara){char*q=p;for(;*p!='';p++)if(*p!=a)*q++=*p;*q='';}功能:输入一行字符,删去指定的字符后输出。 根据形式参数和实际参数的用法可以有以下4种形式:1:实际参数与形式参数均为数组名;2:实际参数为数组名,形式参数为指向数组的指针变量;3:实际参数为指向数组的指针变量,形式参数为数组名;4:实际参数和形式参数均为指向数组的指针变量。关于“地址”做参数的几种情况的说明: 例8.12以下程序的功能是:从键盘上输入一行字符,存入一个字符数组中,然后输出该字符串,请填空.#includevoidmain(){chars[81],*sp;inti;for(i=0;i<80;i++){s[i]=getchar();if(s[i]==‘ ’)break;}s[i]=_____________;sp=s;while(*sp)putchar(*sp________);} 链表链表是一种常见的重要的数据结构,是动态地进行存储分配的一种结构,实现数据在内存中离散的存储。数组存放数据时,必须事先定义固定的长度。链表根据需要开辟内存单元,可以从无到有,一个一个地输入各结点数据。a1a2……an-1an^h(头指针)单向链表的结构值域指针域200089200990300079nullh200020093000 结构体类型的概念姓名电话性别年龄E-mail地址地址张三……12345678…………m……16……zhang@163.com……………………..北京……结构体:是一种数据类型,它把互相联系的数据组合成一个整体——结构体,每个数据项——成员。 构造一个结构体类的数据类型的一般形式:struct结构类型名{类型标识符成员名1;类型标识符成员名2;::类型标识符成员名n;};结构体类型的定义 示例:structAList{charname[21];/*姓名*/longtel;/*电话*/charsex;/*性别*/intage;/*年龄*/chare_mail[40];/*电子邮件*/charaddr[31];/*地址*/};姓名电话性别年龄E-mail地址地址张三12345678m16zhang@163.com北京 定义先构造结构体类的数据类型,后定义具有这种构造的变量。struct结构体类型名{类型标识符成员名1;:类型标识符成员名n;};struct结构体类型名变量名1,变量名2..;结构体变量的定义和引用 示例:structstudent{charnumber[10];charname[21];charsex;intage;floatscore;charaddr[31];};structstudents1,s2;numbernamesexagescoreaddr12345678张三m16526北京 引用对结构体变量的使用是通过对其成员的引用来实现的。引用结构体成员的一般形式如下:结构体变量名.成员名例如s1.age其中的圆点符号称为成员运算符,它的运算级别最高。结构体变量的定义和引用 structstud{charnumber[10];charname[20];intage;charaddr[30];}s1={“9708”,”Liwei",20,"Beijing”};结构体变量的初始化printf(“%d”,s1.age) 例输入3个学生的信息并输出。#include#includestructstud/*定义结构体数据类型*/{longno;/*学号*/charname[20];/*姓名*/charsex;/*性别*/intage;/*年龄*/floatscore;/*成绩*/};应用举例 voidmain(){structstuds[3];/*定义stud结构体类型的数组s*/inti;charc[20];for(i=0;i<3;i++){printf(" 输入第[%d]个学生的数据: ",i);gets(c);s[i].no=atol(c);/*将字符串学号转成长整型*/gets(s[i].name);/*输入姓名*/s[i].sex=getchar();getchar();/*利用输入性别*/gets(c);s[i].age=atoi(c);/*将字符串年龄转成整型*/gets(c);s[i].score=atof(c);/*将字符串成绩转成实型*/} printf(" 学号t姓名tt性别t年龄t成绩 ");for(i=0;i<3;i++){printf("%ldt%-15s",s[i].no,s[i].name);printf("t%ct%dt%6.2f ",s[i].sex,s[i].age,s[i].score);}} a1a2……an-1an^h(头指针)单向链表的结构1.链表的定义(结点的C语句定义)值域指针域 1.链表的定义(结点的C语句定义)首先用结构体类型描述一个数据元素结点格式:structLNode{类型标识符data;/*定义值域*/structLNode*next;/*定义指针域*/};/*定义指向该结构体的指针变量*/值域指针域 示例8-13:编写实现用链表存放n个整数的函数1)定义一个结点类型:structLNode{intdata;structLNode*next;};值域指针域 2)定义一个指向结点类型的指针类型变量:structLNode*p;3)访问结点变量p的各个成员:p->data,p->nextstructLNode{intdata;structLNode*next;};值域指针域 voidsub(structLNode*L,intn){inti;structLNode*p1,*p2;p1=L;p1->next=NULL/*P1指向第一个结点*/for(i=n;i>0;i--){p2=(LNode*)malloc(sizeof(LNode));if(!p2)exit(0);scanf(“%d”,&p2->data);p2->next=p1->next;p1->next=p2;}}算法:1:L接受实参结点指针,且将该结点作为线性链表的头结点2:将其next置空3:循环下列操作n次申请一个空结点读入一个元素值,送入该结点值域中将结点插入到;链表的头结点后面.值域指针域格式:(类型标识符*)malloc(sizeof(类型)) 练习:链表的应用---计算n位同学某门课程的平均成绩。算法:1:定义结点;2:定义sub()完成n位同学成绩的输入(存储)3:定义主函数,完成变量定义,n值输入,sub()函数调用,总成绩及平均成绩的计算,输出结果。 #include#include#includestructLNode{intdata;structLNode*next;};值域指针域 voidsub(structLNode*L,intn){inti;structLNode*p1,*p2;p1=L;p1->next=NULL;/*P1指向第一个结点*/for(i=n;i>0;i--){p2=(structLNode*)malloc(sizeof(structLNode));if(!p2)exit(0);scanf("%d",&p2->data);p2->next=p1->next;p1->next=p2;}}值域指针域 voidmain(){inti,n;doubles,a;structLNode*p;scanf("%d",&n);p=(structLNode*)malloc(sizeof(structLNode));if(!p)exit(0);sub(p,n);p=p->next;for(i=1,s=0;i<=n;i++){printf("%dt",p->data);s=s+p->data;p=p->next;}a=s/n;printf(" 总成绩=%.2f,平均成绩=%.2f",s,a);} 练习1:阅读下列源程序,请写出运行结果。#includevoidmain(){chara[]=”ABCD”,*p=&a[3];while(p>=a)printf(“%s ”,p--);} 练习2:阅读下列源程序,请写出运行结果。#includevoidmain(){chars[]=”159”,*p=s;printf(“%c”,*p++);printf(“%c”,*p++);}结果:15 练习3:阅读下列源程序,请写出运行结果。#includeintb=2;intfun(int*k){b=*k+b;returnb;}voidmain(){inta[10]={1,2,3,4,5,6,7,8},i;for(i=2;i<4;i++){b=fun(&a[i])+b;printf(“%4d”,b);}printf(“ ”);}结果:1028 练习4:以下选项中正确的语句组是。A)chars[];s=“BOOK!”;B)char*s;s={“BOOK!”};C)chars[10];s=“BOOK!”;D)char*s;s=“BOOK!”; 练习5:请将以下程序中的函数声明语句补充完整。#includeint_________________;voidmain(){intx,y,(*p)(int,int);scanf(“%d%d”,&x,&y);p=max;printf(“%d ”,(*p)(x,y));}intmax(inta,intb){return(a>b?a:b);}max(int,int) 练习6:阅读函数,其功能是?intfun(char*a,char*b){while((*a!=‘’)&&(*b!=‘’)&&(*a==*b)){a++;b++;}return(*a-*b);} 练习7:程序中若有如下说明和定义语句,对函数fun的正确调用语句是?charfun(char*);voidmain(){char*s=“one”,a[5]={‘’};char(*f1)(char*)=fun,ch;………}ch=(*f1)(a);B)*f1(*s);C)fun(&a);D)ch=(*f1)(*s); 练习8:下面程序段的运行结果是?chars[80],*sp=“HELLO!”;sp=strcpy(s,sp);s[0]=‘h’;puts(sp); 练习9:下面程序段的运行结果是?#includevoidfun1(char*p){char*q;q=p;while(*q!=‘’){(*q)++;q++;}}voidmain(){chara[]={“Program”},*p;p=&a[3];fun1(p);printf(“%s ”,a);}结果:Prohsbn 练习10:设有以下定义和语句chars[20]=“Program”,*p;p=s;则以下叙述中正确的是A)*p与s[0]中的值相等B)s与p的类型完全相同C)s数组长度和p所指向的字符串长度相等D)数组s中存放的内容和指针变量p中存放的内容相同 本章小结1:指针、地址、变量的指针、数组的指针、函数的指针、字符串的指针、指针变量等基本概念2:指向变量的指针变量、指向数组的指针变量、指向函数的指针变量及指向字符串的指针变量如何定义?3:如何利用指向变量的指针变量来引用变量?如何利用指向数组的指针变量引用数组元素? 本章小结(续)4:指向变量的指针变量、指向数组的指针变量做参数,如何进行参数的传递?5:返回指针值的函数如何定义;6:什么是函数的指针?指向函数的指针变量如何定义?如何赋值?如何利用指向函数的指针变量实现函数的调用? 函数调用中如何应用参数?1:“值”的传递:intf(int);voidmain(){intsum,x,*p=&x;scanf(“%d”,&x);sum=f(x);…………}intf(intx){………………………………}p*px[10],i,*p=x;for(i=0;i<10;i++){scanf(“%d”,p+i);sum=f(x[i]);}…………}sum=f(*(p+i));} 函数调用中如何应用参数?2:“地址”的传递:intf(int*);voidmain(){intsum,x,*p=&x;scanf(“%d”,&x);sum=f(&x);…………}intf(int*x){………………………………}ppx[10],i,*p=x;for(i=0;i<10;i++)scanf(“%d”,p+i);sum=f(x);…………sum=f(p);f(int[]);f(inta[]) 函数调用中如何应用参数?3:二维数组如何实现参数传递的传递:intf(int[][10]);voidmain(){intsum,x[10][10];…………;sum=f(x);…………}intf(inty[][10]){………………………………} 主函数中定义一个5×5的二维数组a,并在主函数中赋值。编写函数f(inta[][5]),函数的功能是:求出数组周边元素的平方的累加和并作为函数值返回给主函数。例如:若a数组中的值为:则返回主程序后s的值应为310。例题: 参考程序:#includeintf(inta[][5]){inti,sum,j;for(sum=0,i=0;i<5;i++){if(i>0&&i<4)//处理第1---3行外围元素的值{sum=sum+a[i][0]*a[i][0]+a[i][4]*a[i][4];continue;}for(j=0;j<5;j++)//处理第0行、第4行外围元素的值sum=sum+a[i][j]*a[i][j];}returnsum;} 参考程序:intmain(){inta[5][5],i,j;for(i=0;i<5;i++)for(j=0;j<5;j++)scanf("%d",&a[i][j]);printf(" ");printf("和:%d ",f(a));return0;} 思考?编写f(inta[][3],intb[][3],intc[][3])函数,计算两个3×3矩阵之和,即c=a+b。在主函数中完成原始数据的输入、函数的调用及运行结果的输出,请编程实现。 补充题:1:想输出a数组的10个元素,用以下程序可以吗?为什么?请修改程序实现题目要求。#includevoidmain(){inta[10]={1,2,3,4,5,6,7,8,9,10},i;for(i=0;i<10;i++,a++)printf(“%d”,*a);} 2:写一个函数,求一个字符串的长度。在main()函数中输入字符串,并输出其长度。3:有一个字符串,包含n个字符。写一函数将此字符串中从第m个字符处开始的全部字符复制成为另一个字符串。4:写一个函数strCmp()实现两个字符串的比较,函数调用形式为strCmp(str1,str2)。如果str1>str2,则此函数值为一正数;若str1==str2,则返回0;若str1intf(char*p)//计算字符串p的长度,并返回{intn;for(n=0;*p!='';n++,p++);returnn;}voidmain(){chars[80];gets(s);printf(" %s的长度:%d ",s,f(s));} /*将字符串中从第m个字符处开始的全部字符复制成为另一个字符串*/#include#includevoidf(char*p1,intm,char*p2){for(p1=p1+m;*p1!='';p1++,p2++)*p2=*p1;*p2='';} voidmain(){intn,m;chars1[80],s2[80];gets(s1);n=strlen(s1);scanf("%d",&m);if(m>n){printf("输入数据非法,结束程序的运行!");return;}f(s1,m,s2);printf(" 处理后的字符串为:%s ",s2);}

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。
关闭