版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、应用指针程序设计 成绩管理中数据的查找与统计案例引入假设学生成绩表如下:任务描述任务描述成绩管理中数据的查找与统计案例引入1.编写函数grade,对于所给成绩一维数组score,学生个数n,分别统计最高分、及格人数和不及格的人数,并返回其值。2.编写函数search,对于所给学生姓名二维数组name,给定学生的姓名(字符串),查询二维数组name中有无给定学生的姓名,有则返回下标值,无则返回-1。任务描述成绩管理中数据的查找与统计案例引入3.编写主函数main,通过键盘输入成绩至一维数组scores中,通过键盘输入学生姓名至二维数组name中,调用自定义函数grade统计最高分、及格人数和不及
2、格的人数,并输出。键盘输入任意学生姓名,调用自定义函数search,查询此学生并输出相应二维数组name中的下标,若没找到则输出“查无此人”。如果希望将学生的学号、姓名、成绩不同数据类型的数据存放在一起,有没有这样一种数据类型(参考结构体)?想一想能力目标1.能够根据程序需要进行指针变量的定义和引用。2.能够运用指针变量的形参接受一维数组和二维数组实参的传递。3.能够运用指针变量的形参接受地址实参的传递,从而实现函数返回多个值。4.能够建立链表,为数据结构中动态链接的物理存储结构打好基础。5.逐步培养程序调试的能力。地址与指针1指针变量的定义与引用2对指针变量的操作3指针与一维数组4指针与二维
3、数组5指针与字符串6指针与函数78知识要求应用指针程序设计指针是C语言中最具特点且广泛使用的数据类型,通过指针不仅可以实现间接地访问变量,而且还可以方便地使用数组、字符串,以及实现内存地址的动态分配,在调用函数时变量改变了的值能够为主调函数使用,即可以从函数调用得到多个可改变的值。只有灵活地掌握了指针的运用,才能编写出简洁、高效的C程序。8.1地址与指针8.1.1内存和内存地址在计算机中,所有的数据都存放在存储器中,内存(内部存储器)是由大规模集成电路芯片组成存储器,包括RAM、ROM。运行中的程序和数据都是存放在内存中的。与内存相对的是外存,外存是辅助存储器(包括软盘、硬盘、光盘),一般用于
4、保存永久的数据。一定要记住:程序、数据是在内存中由CPU来执行和处理的。外存上尽管可以保存程序和数据,但是当这些数据在没有调入内存之前,是不能由CPU来执行和处理的。8.1地址与指针8.1.1内存和内存地址内存是由内存单元(一般称为字节)构成的一片连续的存储空间,为方便地访问这些内存单元,我们为每个内存单元进行了编号,这样有利于根据这些内存单元的编号准确地找到内存单元。通常把这些内存单元的编号就叫做内存地址,简称地址。CPU是通过内存地址来访问内存,进行数据存取(读/写)。8.1地址与指针8.1.2变量、变量名、变量的地址和变量值C程序的编写离不开变量的使用,变量必须遵循“先定义,后使用”的原
5、则。变量定义以后,编译系统就为变量分配相应的内存单元,用于存放各种类型的数据,并将变量名和内存单元地址建立对应的联系。8.1地址与指针8.1.2变量、变量名、变量的地址和变量值与变量有关的几个概念: (1)变量名:是给内存空间取的一个容易记忆的名字。 (2)变量的地址:变量占用的内存空间的地址。 (3)变量值:在变量的地址所对应的内存空间中存放的数值即为变量的值。8.1地址与指针8.1.3指针、变量的指针和指针变量 (1)指针:就是 “内存单元的地址”。指针指向一个内存单元。 (2)变量的指针:就是“变量的地址”。变量的指针指向一个变量对应的内存单元。 (3)指针变量:就是地址变量。地址(指针
6、)也是数据,可以保存在一个变量中。保存地址(指针)数据的变量称为指针变量。8.1地址与指针8.1.3指针、变量的指针和指针变量一般情况下,我们在程序中只需指出变量名,无需知道每个变量在内存中的具体地址,每个变量与具体地址的联系由C编译系统来完成。程序中我们对变量进行的存取操作,实际上也就是对某个地址的存储单元进行操作。这种直接按变量的地址存取变量值得方式称为“直接存取”方式。直接访问将变量a的地址(指针)存放在指针变量p中,p中的内容就是变量a的地址,也就是p指向a,然后利用指针变量p进行变量a的访问。这种通过变量p间接得到变量a的值的方式称为“间接存取”方式。8.1地址与指针8.1.3指针、
7、变量的指针和指针变量间接访问8.2指针变量的定义与引用8.2.1指针变量的定义类型名 * 指针变量名1,*指针变量名2,;例如:int *pt1, *pt2; 定义两个指针变量pt1、pt2,基类型为整型,即指向的数据类型为整型。float *f; 定义指针变量f,基类型为浮点型,即指向的数据类型为浮点型。char *pc; 定义pc,基类型为字符型,即指向的数据类型为字符型。指针变量的定义格式8.2指针变量的定义与引用8.2.1指针变量的定义 (1)C语言变量先定义后使用,指针变量也不例外,为了表示指针变量是存放地址的特殊变量,定义变量时在变量名前加“*”号; (2)指针变量存放地址值,PC
8、机用2个字节表示一个地址,所以指针变量无论什么类型,其本身在内存中占用的空间是2个字节。说明8.2指针变量的定义与引用8.2.2指针变量的引用格式:&变量名功能:取变量的地址优先级:同!,+,-,+,-单目、右结合性例如:int a,*p;p=&a; 以上两条语句可以写成:int a,*p=&a;1.取址运算符(&)8.2指针变量的定义与引用8.2.2指针变量的引用格式:*指针变量功能:取指针变量所指(所存地址对应的)存储单元中的值优先级:同!,+,-,+,-,&单目、右结合性2.间址访问运算符例如:若有以下程序段int a,*p; p=&a;scanf(“%d”,p);(*p)+;print
9、f(“%d,%d”,*p,a);8.3对指针变量的操作8.3.1指针变量的赋值例8.2:指针变量赋值样例。main() int a=5,*p,*q; p=&a; q=p; *q=a+1; printf(%d,%dn,*p,*q);运行结果:6,6 (1)指针变量可以被赋值地址,但基类型必须一致。 例如:p=&a; q=p; (2)可以通过标准函数获得地址值。 例如:p=(int*)malloc(sizeof(int);分配int字节大小的存储单元,返回首地址。p=(int*)calloc(n, sizeof(int);分配n个int字节大小的存储单元,返回首地址。 (3)赋空值。p=NULL;
10、p=0; p=0;8.3对指针变量的操作8.3.1指针变量的赋值说明8.3对指针变量的操作8.3.2指针变量的算术运算(移动)当指针指向一串连续的存储单元(基类型相同)时: (1)指针(指针变量)加1,不是指针的地址值加1,而是加1个指针基类型的字节数; (2)两个指针变量相减:相邻存储单元的个数; (3)不能进行其他算术运算。8.3对指针变量的操作8.3.2指针变量的算术运算(移动)a0 a1 a2 a3 a4 a5pq例如:图(a)q=p+2;例如:图(b)a0 a1 a2 a3 a4 a5P qq+;q+;q-;p+;k=q-p; k为2例8.3:指针变量移动和比较的样例main() i
11、nt a10,*p,*q; p=a; q=&a4; p=a+6; if(pq) printf(“q大于pn”); else printf(“q不大于pn”); printf(“%dn”,q-p); 8.3对指针变量的操作8.3.2指针比较多个指针指向同一个连续的存储单元时,可以进行关系运算。a0 a1 a2 a3 a4 a5 a6 a7 a8 a9pqp程序结果如下:q不大于p-28.4指针与一维数组在C语言中,一维数组名代表一维数组首元素在内存单元的地址。由于数组元素在内存中占用连续的单元,所以,可以用一个指针变量存放首元素的地址,并通过该指针变量的移动访问数组中的各个元素。a+2a a0
12、a1 a2 a3 a9a+1a+9P+1 P+2P+9P数组名就是数组的首地址。例如有int a10; ,则a等价于&a0。当有如下定义和赋值:int a10,*p;p=a;1.指向一维数组的指针8.4指针与一维数组8.4.1通过指针访问一维数组8.4指针与一维数组8.4.1通过指针访问一维数组2.通过首地址引用数组元素 例如:int a10,i; 一般访问形式: 输入:for(i=0;i10;i+) scanf(“%d”,a+i); 输出:for(i=0;i10;i+) printf(“%d”, *(a+i);8.4指针与一维数组8.4.1通过指针访问一维数组例如:int a10,*p,i;
13、 p=a;或p=&a0;(1)不移动指针 输入:for(i=0;i10;i+) scanf(“%d”,p+i); 输出:for(i=0;i10;i+) printf(“%d ”, *(p+i); (2)移动指针 输入:for(;pa+10;p+) scanf(“%d”,p); 输出:for(p=a;pa+10;p+) printf(“%d ”, *p);输出语句中for循环中又初始化p=a,因为在输入语句中p循环后定位在最后元素的下一个位置,所以再输出数组元素的值指针必须指向首地址。切记,不能用a+ 移动指针。小提示3.通过指针变量引用数组元素8.4指针与一维数组8.4.1通过指针访问一维数组
14、总之,一维数组元素的引用可以有如下两大种、4小种: 下标法,数组a的5个元素可表示为:a0、a1、a2、a3、a4; 或:p0、p1、p2、p3、p4。指针法,数组a的5个元素可表示为:*p、*(p+1)、*(p+2)、*(p+3)、*(p+4);或:*a、*(a+1)、*(a+2)、*(a+3)、*(a+4)。4.用带下标的指针变量引用数组元素例如:int a10,*p,i; p=a;或p=&a0; 输入:for(i=0;i10;i+) scanf(“%d ”,p+i); 输出:for(i=0;i10;i+) printf(“%d ”, pi);小提示8.5指针与二维数组8.5.1二维数组和
15、数组元素的地址1.二维数组行地址a由a0、a1、a2三个一维数组组成。数组名a:第一个数组元素的地址,基类型为数组类型(一维数组)。a0:第一个数组元素的地址,基类型为数组元素类型(int)。a0、a1、a2分别为每行第一个元素的地址,基类型为数组元素类型(int)。所以,若有i从0到2行,ai为i行的首地址。又因为,ai等价*(a+i)。所以,*(a+i)是i行第一个元素的地址。8.5指针与二维数组8.5.1二维数组和数组元素的地址1.二维数组行地址P即&a00也是二维数组的首地址,但在使用上与a有一定的区别。p+1指向下一个元素a01,而a+1指向下一行。所以我们通常将p称为列指针(同指向
16、变量的指针),a称为行指针。p= a0;合法,但p=a;不合法(基类型不同)。8.5指针与二维数组8.5.1二维数组和数组元素的地址2.二维数组元素的地址 若有j从0到3列,i行j列元素的地址为: (1)&aij (2)ai+j (3)*(a+i)+j 因为:ai等价*(a+i) (4)&a00+4*i+j(相对第一个元素的地址) (5)a0+4*i+j(相对第一个元素的地址)8.5指针与二维数组8.5.1二维数组和数组元素的地址3.通过元素地址引用二维数组元素 若有定义:int a34,i,j; 数组元素 数组元素地址(1)aij &aij(2)*(ai+j) ai+j(3)*(*(a+i)
17、+j) *(a+i)+j(4)*(&a00+4*i+j) &a00+4*i+j(5)*(a0+4*i+j) a0+4*i+j 8.5指针与二维数组8.5.1二维数组和数组元素的地址4.通过行指针引用二维数组元素按如下格式定义一个二维数组对应的行指针变量:类型说明符 (*指针变量名)所指二维数组的第二维长度值;例如:int a32,(*prt)2; (注意:prt的基类型是2个元素的一维数组类型)则有:prt=a;8.5指针与二维数组8.5.1二维数组和数组元素的地址4.通过行指针引用二维数组元素prt 0+0 prt 0+1 *( prt +0)+0 *( prt +0)+1 prt 1+0
18、prt 1+1 *( prt +1)+0 *( prt +1)+1 prt 2+0 prt 2+1 *( prt +2)+0 *( prt +2)+1 prt+0 a+0prt+1 a+1prt+2 a+2行指针数组首地址:a(基类型:数组)可以通过prt指针访问数组中的元素:(1)prtij(2)*(prti+j)(3)*(*(prt+i)+j) (4)(*(prt+i)j 8.5指针与二维数组8.5.1二维数组和数组元素的地址printf(n); p2=a; for(i=0;iM;i+) for(j=0;jN;j+) printf(%4d,*(p2i+j); printf(n); #inc
19、lude#define M 3#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*/例:二维数组的指针访问8.5指针与二维数组8.5.2函数中二维数组作为实参二维数组名作实参对应形参类型必须为行指针类型,首地址传递。若有定义:double s53;调用(实参):fun(s)定义(形参):fun(double (*a)3)或fun(double a3)或fun(double a53)8.5指针与二维数组8.5.2函数中二维
20、数组作为实参#include#define M 3#define N 2void myout(int (*p)N) /* void myout(int pMN) */ 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; myout(a);例:二维数组作为实参样例。8.6指针与字符串8.6.1通过指针访问字符串常量可以在定义字符指针变量的同时,将存放字符串的存储单元起始地址赋给指针变量。如果定义了一个
21、字符型指针变量,也可以通过赋值运算将某个字符串的首地址赋给它,从而使其指向一个字符串。例如:char *p=Hello;或者: char *p; p=Hello; 8.6指针与字符串8.6.1通过指针访问字符串常量#include main() char *p=Beijing; puts(p); p=Shanghai; for(;*p!=0;p+) putchar(*p);例:通过指针访问字符串程序样例。 (1)可以将字符串常量的首地址赋给指针变量; (2)可以通过移动指针变量依次访问字符串的每一个字符。说明8.6指针与字符串8.6.2通过指针访问字符串数组如果字符串已经存放在某个字符数组中,
22、可以用赋值方式将指针变量指向该字符数组。例如:char str10=Hello,*p; p=str;#includemain() char s150,s220,*p,*q; printf(Input a string:); p=s1; q=s2; gets(s2); while(*q!=0) *p=*q; p+; q+; *p=0; puts(s1);8.6指针与字符串8.6.2通过指针访问字符串数组例:通过地址访问字符串程序样例,两个字符串复制。8.6指针与字符串8.6.3字符串指针作为函数参数字符串指针作为函数参数同一维数组,对应形参类型必须为指针类型,首地址传递。例:输入一个字符串,调用
23、函数实现字符串的逆序存放。void inverse(char *p) char *q,t; int n; n=strlen(p); for(q=p+n-1;pq;p+,q-) t=*p; *p=*q; *q=t; 8.6指针与字符串8.6.3字符串指针作为函数参数#include#includevoid inverse(char*);main() char s81; printf(Input String:); gets(s); printf(Inversed:); inverse(s); puts(s);8.6指针与字符串8.6.4使用字符指针和字符数组处理字符串的讨论虽然用字符数组和字符指
24、针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,主要有以下几点: (1)字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串 的首地址),决不是将字符串放到字符指针变量中。 (2)对字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值。 (3)对字符指针赋初值。8.6指针与字符串8.6.4使用字符指针和字符数组处理字符串的讨论 (4)如果定义了一个字符数组,在编译时即为其分配内存单元,它有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个地址值,也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋予一个地址值,这
25、时该指针变量并未具体指向哪一个字符数据。 (5)指针变量的值是可以改变的。8.7指针与函数8.7.1函数间地址传递问题提出:传值形参的改变不能改变对应实参的值,惟一途径是return语句返回的一个函数值。如何传递多个数值?解决办法:设置指针类型的形参,得到相应实参的地址,变传值为传址。形参:指针类型。实参:基类型相同的地址值或指针变量。8.7.1函数间地址传递例:借助指针变量返回多个值(重点)。#includevoid change2(int *a,int *b) int c; c=*a; *a=*b; *b=c;main() int x=1,y=2; printf(调用前:x=%d,y=%d
26、n,x,y); change2(&x,&y); printf(调用后:x=%d,y=%dn,x,y);运行结果:调用前:x=1,y=2调用后:x=2,y=18.7指针与函数如果函数change2写成如下形式:void change2(int a,int b) int temp; temp=a; a=b; b=temp;8.7.1函数间地址传递这个函数我们在前面介绍过,在函数change2中实现了局部变量(形参)a,b的值的交换,但调用结束后它们的空间释放,主函数中执行change2(x,y)后,x和y的值并未交换。8.7指针与函数为了使在函数中改变了的变量值能被main函数所用,应该用指针变量
27、作为函数参数,在函数执行过程中使指针变量所指向的变量值发生变化,函数调用结束后,这些变量值的变化依然保留下来,这样就实现了“通过调用函数使变量的值发生变化,在主调函数中使用这些改变了的值”的目的。8.7.1函数间地址传递如果想通过函数调用得到n个要改变的值,可以: (1)在主调函数中设n个变量,用n个指针变量指向它们; (2)将指针变量作实参,将这n个变量的地址传给所调用的函数形参; (3)通过形参指针变量,改变该n个变量的值; (4)主调函数中就可以使用这些改变了值的变量。说明8.7指针与函数8.7.2函数型指针函数的指针:函数的入口地址(函数的首地址)。C语言规定函数的首地址就是函数名,所
28、以函数名就是函数的指针。指向函数的指针变量:存放函数入口地址(函数指针)的变量,称为指向函数的指针变量。简称函数的指针变量。函数可以通过函数名调用,也可以通过函数指针调用。8.7指针与函数通过函数指针实现函数调用的步骤: (1)指向函数的指针变量的定义: 类型 (* 函数指针变量名)();例如int (*p)(); 注意:两组括号()都不能少。int表示被指向的函数的类型,即被指向函数的返回值类型。 (2)指向函数的指针变量的赋值,指向某个函数:函数指针变量名=函数名; (3)利用指向函数的指针变量调用函数:(* 函数指针变量名)(实参表)。8.7.2函数型指针8.7指针与函数#include
29、main() int max(int,int); int (*p)(int,int); int a,b,c; p=max; scanf(%d%d,&a,&b); c=(*p)(a,b); printf(a=%d,b=%d,max=%dn,a,b,c);int max(int x,int y) int z; z=xy?x:y; return z;8.7.2函数型指针例:用指向函数的指针求两个数中较大者。8.7指针与函数8.7.3指针型函数函数可以返回整型、实型、字符型等类型的数据,还可以返回地址值-即返回指针值。我们称返回值为指针类型的函数为指针型函数。返回指针值的函数定义:类型名 * 函数名(
30、参数表)例如:int *fun(int x,int y)定义了一个函数fun,调用它后能得到一个指向整数型数据的指针。指针型函数在动态链表中经常使用。8.7指针与函数#includeint *fun(int,int);main() int i,j,*p; printf(enter two num to i,j:); scanf(%d%d,&i,&j); p=fun(i,j); /* 调用fun,返回大数地址,赋值给指针变量p */ printf(max=%dn,*p); /* 打印p指向的数据 */int *fun(int x,int y) /* fun函数返回形参x,y中较大数的地址(指针)
31、 */ int *z; if(xy)z=&x; else z=&y; return z;8.7.3指针型函数例:返回两个数中大数地址的函数。结果:enter two num to i,j:12 38max=388.7指针与函数8.7.4指针数组和指向指针的指针1.指针数组若一个数组的元素均为指针类型数据,则称为指针数组。指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。指针数组的定义说明形式为:类型说明符 *数组名常量表达式;例如:int *p4;注意,不要写成“int (*p)4;”,这是指向一维数组的指针变量。8.7指针与函数8.7.4指针数组和指向指针的指针#inc
32、lude#includemain()void sort(char *name,int n); void print(char *name,int n); char *name=FORTRAN,BASIC,LISP,Pascal,C,PROLOG,Java;int n=7;sort(name,7);print(name,7);例:将若干字符串按字母顺序(由小到大)输出。8.7指针与函数void sort(char *name,int n) char *temp; int i,j,k; for(i=0;in-1;i+) k=i; for(j=i+1;j0)k=j; if(k!=j) temp=na
33、mei;namei=namek;namek=temp; void print( char *name,int n) int i; for(i=0;i可执行文件名 参数1 参数2 参数n其中“可执行文件名”就是源程序(.C)经编译连接后生成的可执行程序(.EXE,含盘符、路径),各参数为字符串(不需要加双引号)。argc参数表示命令行中参数的个数(注意:文件名本身也算一个参数),其值是在输入命令行时由系统按实际参数的个数自动赋予的;argv含有argc个元素,分别存放各参数字符串的首地址。2.指针数组作为main函数的参数8.7指针与函数main(int argc,char argv) while(argv1) +argv; printf(“%sn”,*argv); -argc; 8.7.4指针数组和指向指针的指针如果有以下main函数
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中学食堂厨师招聘合同
- 机场物业管理招投标文件样本
- 政府办公楼环境卫生合同
- 冷链物流运输质量控制
- 物流中心车位租赁协议
- 儿童游乐场场地租赁合同范本
- 大型舞台设备维修吊车租赁合同
- 文化传媒公司董事长招聘协议
- 房地产销售技巧培训
- 印刷包装物流服务投标模板
- 20世纪时尚流行文化智慧树知到期末考试答案章节答案2024年浙江理工大学
- 国开(甘肃)2024年春《地域文化(专)》形考任务1-4终考答案
- (高清版)JTGT 3331-04-2023 多年冻土地区公路设计与施工技术规范
- 基于PLC的谷物烘干机控制系统设计--程序代码-附 录
- 社区治安巡逻队工作方案
- GHTF—质量管理体系--过程验证指南中文版
- 信用社(银行)借新还旧申请书(精编版)
- (完整版)苏教版五年级数学上册知识点归纳总结
- lampsite LTE 站点配置指导v1.1
- 放射性口腔粘膜炎的发病机制及危险因素
- 美能达807si相机中文说明书
评论
0/150
提交评论