模块8应用指针程序设计电子课件 C语言程序设计案例教程.pptx
《模块8应用指针程序设计电子课件 C语言程序设计案例教程.pptx》由会员分享,可在线阅读,更多相关《模块8应用指针程序设计电子课件 C语言程序设计案例教程.pptx(88页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C语言程序设计案例教程作者:模块8 应用指针程序设计假设学生成绩表如表4-1所示。(1)编写函数fn1,建立n个学生的期末考核成绩和姓名。(2)编写函数fn2,对于n个学生的期末考核成绩,分别统计平均分、最高分、及格人数和不及格的人数,并返回其值。(3)编写函数search,对于所给学生姓名,输入待查找的学生姓名,在所有学生中查找给定的学生,有则返回下标值,无则返回-1。(4)编写主函数main,调用fn1录入学生姓名和期末考试成绩;调用fn2统计平均分、最高分和及格人数,并输出;调用search在学生中查找某个学生。如果希望将学生的学号、姓名、成绩等不同数据类型的数据存放在一起,有没有这样一
2、种数据类型(预习模块9)?任务描述模块8 应用指针程序设计(1)能够掌握指针的基本概念和基本应用方法,为数据结构中动态链接的物理存储结构打好基础。(2)能够根据程序需要进行指针变量的定义和引用。(3)能够运用指针变量的形参接受一维数组和二维数组实参的传递。(4)能够运用指针变量的形参接受地址实参的传递,从而实现函数返回多个值。(5)逐步培养程序调试的能力。任务目标模块8 应用指针程序设计#include#include#define N 5void fn1(float*a,char name8)int i;printf(n);for(i=0;iN;i+)printf(请输入第%d位学生的姓名:
3、,i+1);源代码展示模块8 应用指针程序设计scanf(%s,namei);printf(请输入第%d位学生期终考核成绩(score):,i+1);scanf(%f,a+i);float fn2(float*a,float*max,int*l)int i;float sum=0;*l=0;源代码展示模块8 应用指针程序设计*max=-1;for(i=0;i=60)+(*l);if(*(a+i)*max)*max=*(a+i);return sum/N;int search(char(*name)8,char*c)源代码展示模块8 应用指针程序设计int i;for(i=0;iN;i+)if(
4、strcmp(namei,c)=0)return i;return-1;main()float scoresN,max,avg;char namesN8,ch8;源代码展示模块8 应用指针程序设计int i,n,k;while(1)system(cls);printf(tt*n);printf(tt1.录入学生姓名及成绩n);printf(tt2.成绩统计n);printf(tt3.查询n);printf(tt0.退出n);printf(tt*nn);源代码展示模块8 应用指针程序设计printf(tt请输入您的选择(0,1,2,3);scanf(%d,&i);if(i=1)fn1(score
5、s,names);else if(i=2)avg=fn2(scores,&max,&n);printf(n平均分为%6.1f,最高分为%6.1f,及格人数为%d,不及格源代码展示模块8 应用指针程序设计人数为%dn,avg,max,n,N-n);else if(i=3)printf(n请输入您查找的姓名:n);scanf(%s,ch);k=search(names,ch);if(k=-1)printf(n查无此人n);else printf(n%d%sn,k,namesk);源代码展示模块8 应用指针程序设计else if(i=0)break;getch();程序运行结果如图8-1、图8-2所
6、示。源代码展示运行结果模块8 应用指针程序设计本程序由4个函数组成。fn1函数用来录入学生姓名及成绩,数据分别用指针和数组作为函数参数传递数据;fn2函数用来统计n个成绩的平均分、最高分、及格人数,平均分借助return返回,最高分和及格人数借助指针参数传递数据;search函数用来在一组名字中查找某个名字,注意函数中两个参数的定义,在主函数中使用调用语句“k=search(names,ch);”,然后根据k的值选择输出。main函数中定义一个while语句,条件总是1,但在循环体中一旦选择0就跳出循环,否则执行某种操作后系统继续显示提示菜单,供用户选择操作。指针是C语言中最具特点且广泛使用的
7、数据类型,通过指针不仅可以间接访问变量,还可以方便地使用数组、字符串,可有效地描述各种数据结构,能够动态地分配内存空间,还可在函数之间传递各种类型的数据。灵活地掌握指针的运用,可以编写出简洁、高效的C程序。程序分析8.1 指针变量的定义与引用在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。由于指针变量存放的可能是不同类型变量的地址,所以指针变量也可以分为不同的类型。8.1.1定义一个指针变量定义指针变量的格式如下。类型名*指针变量名1,*指针变量名2,例如:int*pt1,*pt2;/*定义了两个指针变量pt1、pt2,
8、基类型为整型,即指向的数据类型为整型*/float*f;/*定义指针变量f,基类型为浮点型,即指向的数据类型为浮点型*/char*pc;/*定义指针变量pc,基类型为字符型,即指向的数据类型为字符型*/需要说明如下两点。(1)C语言变量先定义后使用,指针变量也不例外,为了表示指针变量是存放地址的特殊变量,定义变量时在变量名前加“*”号。(2)指针变量存放地址值,计算机用2字节表示一个地址,所以指针变量无论什么类型,其本身在内存中占用的空间都是2字节。8.1.2指针变量的引用指针变量一定要有确定的值以后才可以使用。禁止使用未初始化或未赋值的指针,因为此时的指针变量指向的内存空间是无法确定的,使用
9、它可能导致系统崩溃。1.取址运算符(&)可以用取址运算符&获得变量的地址,格式如下。&变量名例如:int a,*p;p=&a;以上两条语句也可以写成:int a,*p=&a;8.1.2指针变量的引用2.间接访问运算符(*)可以通过间接访问运算符“*”获得指针变量所指单元中的值,格式如下。*指针变量例如:int a,*p;p=&a;scanf(%d,p);(*p)+;printf(%d,%d,*p,a);若输入12,则输出为:13,138.2 指针变量作为函数参数函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型。它的作用是将一个变量的地址传递到另一个函数中。到目前为止,我们知道函数
10、传值形参的改变不能改变对应实参的值,把数据从被调函数返回到调用函数一般是通过return语句返回函数值,这就限定了只能返回一个数据,那么如何传递多个数值?解决办法是设置指针类型的形参,得到相应实参的地址,变传值为传址。形参是指针类型,实参是基类型相同的地址值或指针变量。【例8-1】借助指针变量返回多个值。程序代码如下。#include 8.2 指针变量作为函数参数void change2(int*a,int*b)int c;c=*a;*a=*b;*b=c;main()int x=1,y=2;8.2 指针变量作为函数参数printf(调用前:x=%d,y=%dn,x,y);change2(&x,
11、&y);printf(调用后:x=%d,y=%dn,x,y);程序运行结果如下。调用前:x=1,y=2调用后:x=2,y=1如果函数change2写成如下形式:void change2(int a,int b)8.2 指针变量作为函数参数int temp;temp=a;a=b;b=temp;在函数change2中实现了交换局部变量(形参)a,b的值,但调用结束后它们的空间释放,主函数中执行change2(x,y)后,x和y的值并未交换。因此,为了使在函数中改变了的变量值能被main()函数所用,应该用指针变量作为函数参数,在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变
12、量值的变化依然保留下来,这样就实现了“通过调用函数使变量的值发生变化,在主调函数中使用这些改变了的值”的目的。8.3 指针与一维数组在C语言中,一维数组名代表一维数组首元素在内存单元的地址。由于数组元素在内存中占用连续的单元,所以,可以用一个指针变量存放首元素的地址,并通过该指针变量的移动访问数组中的各个元素。8.3.1 通过指针访问一维数组1.指向一维数组的指针我们知道,数组名就是数组的首地址。例如,有“int a10;”,则a等价于&a0。若有以下定义和赋值:int a10,*p;p=a;则将指针变量p指向数组的首元素。数组元素ai的地址可以用a+i来表示,也可以用p+i表示。指针与数组的
13、关系如图83所示。图8-3指针与数组的关系可见,p值与&a0相等,p+1的值与&a1相等,p+i的值与&ai相等。8.3.1 通过指针访问一维数组需要注意以下几点。(1)p+是正确的,而a+是错误的,因为a是数组名,是常量。(2)由于+与*同优先级,结合方向自右向左,故*p+等价于*(p+)。(3)*(p+)与*(+p)的值不同,*(p+)等价于a0,*(+p)等价于a1,但p的值均变成了&a1,即p指向a1。(4)(*p)+表示p所指向的元素值增1。2.通过首地址引用数组元素对数组元素的访问我们之前采用的是下标方式。既然数组名a就是数组的首地址,因此我们可以使用“a+i”,通过i的变化依次访
14、问数组元素。例如:int a5,i;一般访问形式如下。8.3.1 通过指针访问一维数组for(i=0;i5;i+)/*一维数组的输入*/scanf(%d,a+i);for(i=0;i5;i+)/*一维数组的输出*/printf(%d,*(a+i);3.通过指针变量引用数组元素要通过指针变量访问数组就必须先将指针变量指向该数组。利用指针变量引用数组元素可以采用“不移动指针”或“移动指针”两种方法。例如:int a5,*p,i;p=a;或p=&a0;1)不移动指针for(i=0;i5;i+)/*一维数组的输入*/8.3.1 通过指针访问一维数组scanf(%d,p+i);for(i=0;i5;i+
15、)/*一维数组的输出*/printf(%d,*(p+i);2)移动指针for(;pa+5;p+)/*一维数组的输入*/scanf(%d,p);for(p=a;pa+5;p+)/*一维数组的输出*/printf(%d,*p);移动指针时,当执行完第一个for语句时,指针指向最后一个元素的下一个位置。所以在输出操作的for循环中,又初始化p=a,让指针指向首地址。4.用带下标的指针变量引用数组元素8.3.1 通过指针访问一维数组若一个指针变量已经指向要访问的数组,则可以同普通数组下标访问一样,使用带下标的指针变量引用数组元素。例如:int a5,*p,i;p=a;或p=&a0;for(i=0;i5
16、;i+)/*一维数组的输入*/scanf(%d,p+i);for(i=0;i5;i+)/*一维数组的输出*/printf(%d,pi);8.3.2 函数中一维数组作为实参数组名作为实参传送,但数组名本身是一个地址,因此,对应的形参应当是一个指针变量,指针变量的基类型必须与数组的类型一致。在函数中,通过指针变量来引用调用函数中对应的数组元素,从而对调用函数中对应的数组元素进行操作来改变其中的值。【例8-2】选择法排序(一维数组作为实参)。程序代码如下。#include#define N 10void mysort(int*p,int n)int i,j,k,t;8.3.2 函数中一维数组作为实参
17、for(i=0;in-1;i+)k=i;for(j=i+1;jpj)k=j;t=pi;pi=pk;pk=t;void myout(int*p,int n)int i;8.3.2 函数中一维数组作为实参for(i=0;in;i+)printf(%4d,*(p+i);printf(n);main()int aN,i,*q;printf(Input Data:);q=a;for(i=0;iN;i+)scanf(%d,q+);8.3.2 函数中一维数组作为实参printf(Before sorted:);myout(a,N);/*输出一维数组的数据,也可以为q=a;myout(q,N);*/mysor
18、t(a,N);/*一维数组的数据排序*/printf(After sorted:);myout(a,N);/*输出排序后一维数组的数据*/程序执行情况如下:Input Data:22 33 4 55 77 54 18 89 5 38Before sorted:2233 45577541889 538After sorted:4 51822333854557789本程序定义了两个函数mysort和myout,两个函数的参数都是指针变量p。用一维数组名作为实参时,数组a 的首地址传给形参p,用指针变量p间接访问数组中的各个元素。但C语言允许写成传统数组表示形式如mysort(int p,int n
19、),便于理解。8.4 指针与二维数组用指针变量可以指向一维数组中的元素,也可以指向二维数组中的元素。但在概念和使用上,二维数组的指针比一维数组的指针要复杂一些。8.4.1 二维数组和数组元素的地址1.二维数组行地址在C语言中,一维数组名代表了该数组的起始地址。由于一个数组被定义了以后,其起始地址是不会改变的,因此数组名实际上是一个指针常量。当一个指针变量指向一个一维数组之后,对数组元素的访问既可以通过下标也可以通过指针来完成。实际上,以上结论可以推广到二维数组乃至多维数组。C语言用一维数组来表示二维数组,即二维数组是以一维数组为元素的一维数组。例如,二维数组a34可以看作有图8-4所示的关系。
20、8.4.1 二维数组和数组元素的地址a由a0、a1、a2三个一维数组组成。数组名a:第一个数组元素的地址,基类型为数组类型(一维数组)。a0:第一个数组元素的地址,基类型为数组元素类型(int)。a0、a1、a2分别为每行第一个元素的地址,基类型为数组元素类型(int)。所以,若有i从0到2行,ai为i行的首地址。又因为ai等价于*(a+i),所以*(a+i)是i行第一个元素的地址。p即&a00,也是二维数组的首地址,但在使用上与a有一定的区别。p+1指向下一个元素a01,而a+1指向下一行。所以我们通常将p称为列指针(同指向变量的指针),a称为行指针。“p=a0;”合法,但“p=a;”不合法
21、(基类型不同)。8.4.1 二维数组和数组元素的地址2.二维数组元素的地址aij元素的地址可以表示为以下几种形式。(1)&aij。(2)ai+j。(3)*(a+i)+j,因为ai等价于*(a+i)。3.通过行指针引用二维数组元素定义一个二维数组对应的行指针变量的格式如下。类型名(*指针变量名)所指二维数组的第二维长度值;例如:int a32,(*prt)2;/*注意:prt的基类型是2个元素的一维数组类型)*/8.4.1 二维数组和数组元素的地址若有“prt=a;”,则可以通过prt指针访问数组中的aij元素,有以下几种访问形式。(1)prtij。(2)*(prti+j)。(3)*(*(prt
22、+i)+j)。(4)(*(prt+i)j。a是常量,prt是变量。【例8-3】通过指针访问二维数组。程序代码如下。#include#define M 38.4.1 二维数组和数组元素的地址#define N 2main()int aMN=1,2,3,4,5,6,i,j,*p1,(*p2)N;p1=a0;for(i=0;i6;i+)printf(%4d,*p1);p1+;/*输出1 2 3 4 5 6*/printf(n);8.4.1 二维数组和数组元素的地址p2=a;for(i=0;iM;i+)for(j=0;jN;j+)printf(%4d,*(p2i+j);printf(n);程序运行结果
23、如下。1 2 3 4 5 61 23 45 68.4.2 函数中二维数组作为实参当用二维数组名作为实参时,对应的形参类型应该是行指针变量。在函数首部可以用数组的形式定义行指针,在被调用函数中也可以使用下标的形式访问行指针所指向的存储单元。若主函数中有以下定义和函数调用:main()int a34;fun(a);8.4.2 函数中二维数组作为实参则fun函数的首部可以是以下3种形式之一。(1)void fun(int(*p)4)。(2)void fun(int p34)。(3)void fun(int p4)。【例8-4】二维数组名作为实参。程序代码如下。#include#define M 3#
24、define N 2void myout(int(*p)N)/*void myout(int pMN)*/8.4.2 函数中二维数组作为实参int i,j;for(i=0;iM;i+)for(j=0;jN;j+)printf(%4d,pij);/*printf(%4d,*(*(p+i)+j);*/printf(n);main()int aMN=1,2,3,4,5,6;8.4.2 函数中二维数组作为实参myout(a);程序运行结果如下。1 23 45 68.5 指针与字符串在C语言中,除了可以通过字符数组对字符串进行引用外,还可以通过字符型指针变量对字符串进行引用。8.5.1 通过指针访问字符
25、串常量可以在定义字符指针变量的同时,将存放字符串的存储单元起始地址赋给指针变量。如果定义了一个字符型指针变量,也可以通过赋值运算将某个字符串的首地址赋给它,从而使其指向一个字符串。例如:char*p=Hello;或char*p;p=Hello;【例8-5】通过指针访问字符串。程序代码如下。#include main()8.5.1 通过指针访问字符串常量char*p=Beijing;puts(p);p=Shanghai;for(;*p!=0;p+)putchar(*p);程序运行结果如下。BeijingShanghai8.5.2 通过指针访问字符串数组如果字符串已经存放在某个字符数组中,可以用赋
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 模块8应用指针程序设计电子课件 C语言程序设计案例教程 模块 应用 指针 程序设计 电子 课件 语言程序设计 案例 教程
限制150内