已阅读5页,还剩59页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7部分 指针、指针与数组,编程步骤: 分析程序框架(粗算法)细算法程序调试,2,本讲内容和目标要求,正确理解指针的概念 理解指针作函数参数时,函数的调用过程 掌握指针与一维数组、二维数组的关系 掌握与动态内存分配相关的三个库函数,并了解动态数组的用法 至少能够读懂指针相关的程序,掌握指针在编程中的作用,3,新的概念:指针(Pointer),指针也是一种数据类型 一种特殊的数据类型,这种类型存储的是地址 C/c+的特色 有些复杂但很实用 指针变量与指针常量 指针变量 专门存放地址数据的变量 指针常量 指一个固定的地址,例如:数组名,4,两种寻址方式,如何读写内存中的数据? 通过变量的地址访问变量所在的存储单元 两种寻址方式 直接(寻址)引用 直接按变量地址来存取变量内容的引用方式 间接(寻址)引用 通过指针变量来间接存取它所指向的变量的引用方式,直接寻址,间接寻址,5,间接寻址访问: int i; int *pi; pi=,例1:直接寻址与间接寻址的表示,直接寻址访问: int i; i=3;,如果能直接寻址那当然就不用间接寻址了,但有时,只能用间接寻址的方法解决问题,数据类型:int *(指向整型变量的指针) 变量名称:pi 变量的初值:&i 含义:向系统申请一个动态区的内存空间,用来存储整型指针变量pi的初值&i,即将pi指向了变量i。,通过*pi这种形式,实现对变量i的间接引用。,2000,3,6,为什么引入指针的概念,指针有如下好处: 为函数提供修改变量值的手段 为C的动态内存分配系统提供支持 可以改善某些子程序的效率 为动态数据结构(如例链表、队列、二叉树等)提供支持,7,int i,*p; p=,int i,*p=,int i; float *p; p=,int *p; p=100;,判断对错!,必须进行赋值才能引用!否则p指向了哪呢?,一个指针变量不能指向与其类型不同的变量!float又称变量P的基类型,应在类型相同的指针变量之间赋值,int *p; scanf(“%p”,指针变量只 存放地址!,int *p; *p=100;,对指针变量赋值只能通过&求得!,8,例2:读程序,#include void main() int a=5,b=10; int *pa= ,读程序的关键: 指针变量指向哪儿? 所指向的变量里存储的数据是多少? 更改的是指针还是指针所指向的变量?,-1,9,指针变量与其它类型变量的对比,共性 在内存中占据一定大小的存储单元 先定义,再使用 指针变量的特殊性 指针变量只能存放地址,而不能存放数据 必须初始化后才能使用,否则指向不确定的存储单元 只能指向同一基类型的变量,否则warning. 可参与的运算:加、减、关系、赋值,10,主调函数,被调函数,void main() int a, b; a = 5; b = 9; Swap(a, b); printf (“a=%d,b=%d“,a,b); ,void Swap(int x, int y) int temp; temp = x; x = y; y = temp; ,5,5,a,b,实 参,形 参,9,9,传数值调用,x,y,5,temp,9,5,因为在局部变量的作用域外无法直接引用,所以无法交换成功。 如何交换作用域外两个变量的值?(例3) 间接引用!,11,主调函数,被调函数,void main() int a, b; a = 5; b = 9; Swap( ,void Swap(int *pa, int *pb) int temp; temp = *pa; *pa = *pb; *pb = temp; ,&a,实 参,形 参,&b,传地址调用,x,y,5,temp,5,a,b,9,9,5,指针的好处之一: 通过间接引用改变了其它作用域内变量的值。 当计算结果不只一个时,可以用这种方法,实现数据的“返回”。,12,习题7.1,下面的函数用于计算两个整数之和,并通过指针形参z得到x和y相加后的结果。,void Add(int x,int y, z) = x+y; ,int *,*z,13,习题7.2,函数功能为_ void Exchange(int *p1, int *p2) int p; p = *p1; *p1 = *p2; *p2 = p; A)交换*p1和*p2的值 B)正确,但无法改变*p1和*p2的值 C)交换*p1和*p2的地址 D)可能造成系统故障,14,小结1,指针的基础知识 寻址方式 指针的概念、定义、赋值、间接引用,15,例4 读程序,#include void main ( ) int a=2,4,6,8,10; int y=0,i,*p; p= ,两个重要内容: 指针指向了哪个数组元素? 是指针运算还是数组元素运算,2 4 6 8 10,16,指针运算地址运算,单个指针的运算 加减运算:每加(减)1表示指针指向后(前)一个数据单元 例:p+;-p;p=p+n; 两个指针的运算 比较:用来比较两个指针的前后位置 例: (p1p2) 相减:两个指针相距多远?,主要用于对数组的处理,17,用数组名(指针常量) 引用数组元素,6000 6001 6002 6003 6004 6005 6006 6007,a,a+1,a+2,void main() int a10,i; puts(“please input %d score:”,N); for (i=0; i10; i+) scanf(“%d“, ,输入输出数组元素:方法1:数组名下标,void main() int a10 ,i; puts(“please input %d score:”,10); for (i=0; i10; i+) scanf(“%d”, ? ); for (i=0; i10; i+) printf(“%d “, ? ); ,输入输出数组元素: 方法2:数组名+偏移量,a+i,*(a+i),18,用指针变量引用数组元素,main() int a10, i; int *p=a; puts(“please input %d score:”,10); for (i=0; i10; i+) scanf(“%d“, ,输入输出数组元素: 方法3:指针变量下标,也可以用指针变量引用一维数组元素 int a10,*p=a;,6000 6001 6002 6003 6004 6005 6006 6007,a,p+1,p+2,main() int a10 ,i; int *p=a; puts(“please input %d score:”,10); for (i=0; i10; i+) scanf(“%d”, ? ); for (i=0; i10; i+) printf(“%d “, ? ); ,输入输出数组元素: 方法4:指针变量+偏移量,p+i,*(p+i),19,用指针变量引用数组元素,main() int a10 , i; int *p; for (p=a; p(a+10); p+) scanf(“%d“, p); for (p=a; p(a+10); p+) printf(“%d “, *p); ,输入输出数组元素: 方法5:指针变化,也可以用指针变量引用一维数组元素 int a10,*p=a;,6000 6001 6002 6003 6004 6005 6006 6007,a,p+,p+,通过数组名的变化引用数组元素行不行?,数组元素的引用形式 ai或*(a+i) pi或*(p+i) *(p+),20,例5 读程序,#include void main() int a = 1,2,3,4,5; int *p = NULL; p = a; printf(“%d, “,*p); printf(“%d, “,*(+p); printf(“%d, “,*+p); printf(“%d, “,*(p-); printf(“%d, “,*p+); printf(“%d, “,*p); printf(“%d, “,+(*p); printf(“%d, “,*p); ,1,2,3,3,2,3,4,4,两个重要内容: 指针指向了哪个数组元素? 是指针运算还是数组元素运算,21,区分几个表达式,P+ *p+ *(p+) *(+p) (*p)+,指向下一个地址单元 间接引用p指向的数据单元,然后,p指向下一个地址单元 同上 先将p指向下一个地址单元,然后间接引用p指向的数据单元 P指向的数据+1,22,例6 读程序,#include void main() int i = 0; char b = “program“; char *a = “PROGRAM”; /*定义一个指针变量指向字符串,与上边定义的区别是:前者是先申请内存空间,后存入字符串,而后者是先将字符串存入在内存的某个地方,然后再用a指向该字符串所在内存的开始位置。另外。b是常量,a是变量*/ printf(“%c%sn“,*a, b + 1); while (putchar (*(a + i) i+; printf(“i = %dn“,i); while ( - i) putchar (*(b + i); printf(“n%sn“, ,Program PROGRAM i=7 margor gram,23,例7:编写函数实现求和1,float sum(float a,int n) int i;float sum= a 0; for(i=1;in;i+) sum+= a i; return(sum); ,#include float sum(float a,int n); void main() int i; float sco4,s; for(i=0;i4;i+) scanf(“%f”, ,形参是数组名,实参是数组名,24,例7:编写函数实现求和2,float sum(float *a,int n) int i;float sum= a 0; for(i=1;in;i+) sum+= a i; return(sum); ,#include float sum(float *a,int n); void main() int i; float sco4,s; for(i=0;i4;i+) scanf(“%f”, ,形参是指针,实参是数组名,25,例7:编写函数实现求和3,float sum(float *a,int n) int i;float sum= a 0; for(i=1;in;i+) sum+= a i; return(sum); ,#include float sum(float *a,int n); void main() int i; float sco4,s; float *p=sco; for(i=0;i4;i+) scanf(“%f”, ,形参是指针,实参是指针,26,例7:编写函数实现求和4,float sum(float a4,int n) int i;float sum= a 0; for(i=1;i4;i+) sum+= a i; return(sum); ,#include float sum(float a,int n); void main() int i; float sco4,s; float *p=sco; for(i=0;i4;i+) scanf(“%f”, ,形参是数组名,实参是指针,27,总之, 数组作函数参数有下列四种写法:,但无论哪种形式,本质上,传递的都是数组的首地址。,28,小结2,指针与一维数组的关系 如何利用指针引用数组元素 形参是指针变量 学习指针的关键: 是对地址处理,还是对数据处理? 何时有*,何时无*,29,作业2,编写函数 void strcat(int *p1,int *p2) 并在主函数中调用。,30,习题7.3,1下列对字符串的定义中,错误的是: 。 A) char str7 = “FORTRAN“; B) char str = “FORTRAN“; C) char *str = “FORTRAN“; D) char str = F,O,R,T,R,A,N,0; 2以下程序段的输出结果是:_ 。 char a = “ABCDE“ ; char *p = NULL; for (p=a; pa+5; p+) printf(“%sn“, p); ,A)ABCDE B)A C)E D)ABCDE B D BCDE C C CDE D B DE E A E,31,下面函数实现strlen函数的功能,即计算指针p所指向的字符串中的实际字符个数。 unsigned int MyStrlen(char *p) int len; len = 0; for (; *p != ; p+) len ; return ; ,0,+,len,习题7.4,32,下面函数也是实现strlen函数功能的,但计算字符串s中的实际字符个数的方法与上一道题有所不同。 unsigned int MyStrlen(char s) char *p = s; while (*p != ) p+; return ; ,0,p-s,习题7.5,33,习题7.6,int MyStrcmp(char s, char t) int i; for (i=0; si = ti; i+ ) if (si = ) return 0 ; return ( ); ,0,si-ti,34,下面函数实现strcmp函数的功能,即比较两个字符串的大小,将两个字符串中第一个出现的不相同字符的ASII码值之差作为比较的结果返回,返回值大于0表示第一个字符串大于第二个字符串,返回值小于0表示,表示第一个字符串小于第二个字符串,当两个字符串完全一样时,返回值为0。 int MyStrcmp(char *p1, char *p2) for (; *p1 = *p2; p1+,p2+) if (*p1 = 0) return ; return ; ,0,*p1-*p2,习题7.7,35,指针与二维数组,#define M 2 #define N 3 int bMN; 两种观点: 看成一个一维数组 看成数组的数组,36,将二维数组看成一个一维数组,int bMN; 二维数组b相当于一个有6个元素的一维数组 若有int *p=(总之是列地址) bij相对于数组起始地址的偏移量为i*N+j 则pi*N+j或*(p+i*N+j)表示每一个数组元素。,37,填空题:求二维数组元素的和,#include void main() int a34=1,3,5,7,9,11,13,17,19,21,23; int i,j,sum=0,*p= ; for ( i=0 ;i3;i+) for(j=0; j4; j+) sum+=p ; printf(“sum=%4d“,sum); ,a0或&a00,i*4+j,38,#include void main() int a34=1,3,5,7,9,11,13,17,19,21,23; int *p= ; for ( ; ;p+) if ( )%4=0) printf(“n“); printf(“%4d“, ); ,填空:输出二维数组元素的值,1 3 5 7 9 11 13,输出结果: 1 3 5 7 9 11 13 15 17 19 21 23,a0或&a00,pa0+12,p-a0,*p,39,将二维数组看成数组的数组,行地址,将二维数组的每一行看成一维数组,*(b+1),*(b+0),再将二维数组b看成由b0,b1两个元素组成的一维数组,注意: b0,b1存放的是每行的首地址,40,指针与二维数组,行地址,b+0,b+1,一维数组b,b,b1 *(b+1),b0 *(b+0),列地址,b0+0 b0+1 b0+2 *(b+0)+0 *(b+0)+1 *(b+0)+2,一维数组b0,b1+0 b1+1 b1+2 *(b+1)+0 *(b+1)+1 *(b+1)+2,列地址,b10 b11 b12 *(*(b+1)+0) *(*(b+1)+1) *(*(b+1)+2),b00 b01 b02 *(*(b+0)+0) *(*(b+0)+1) *(*(b+0)+2),一维数组b1,请注意:这样的一维数组只是一个示意图,并不在内存中存在。,41,指针与二维数组,b 代表二维数组的首地址,指向第0行的首地址(行地址) b+i 指向第i行的首地址(行地址) *(b+i) 或 bi 代表第i行第0列的地址(列地址) *(b+i)+j 或 bi+j 代表第i行第j列的地址(列地址) *(*(b+i)+j ) 或 bij 代表第i行第j列的元素(数组元素),42,用数组名引用二维数组元素,元素bij的几种等价的引用方式 bij *(bi+j) *(*(b+i)+j) (*(b+i)j,如何用指针变量引用二维数组元素?,43,习题7.8,设有语句:int array34; 则在下面几种引用下标为i和j的数组元素的方法中,不正确的引用方式是:_ A)arrayij B)*(*(array + i) + j) C)*(arrayi + j) D)*(array + i*4 + j),D,44,二维数组与指针,用指针指向二维数组,有两种指针: 列指针,这种指针指向二维数组的每一个元素,它每加1,指向二维数组的下一个数组元素。 行指针,这种指针指向二维数组的行,它每加1,指向二维数组的下一行。 上边两种指针分别对应着对二维数组的两种看法。,45,二维数组的行指针,行指针指向二维数组的行 例:int (*p) 3; 含义:定义一个指针变量p,用于指向一行(每行有3个元素) 定义格式 :类型 (*行指针名) 常量N;,要用p指向数组b,如何初始化? p=b(或p=/*用行地址初始化*/ p+的含义是? 指向b1,即指向下一行的开始位置,是行地址。 如何用P引用b中每一个数据元素? pij *(pi+j) *(*(p+i)+j) (*(p+i)j,46,#include void main() char a510=“abcde“,“abc“,“abcd“,“ab“,“abcdef“; char (*p)10; int i; for(i=0;i5;i+) p=a+i; printf(“%sn”,*p); p=a+2; p+; printf(“*p=%cn“,*p); ,例8二维数组与指针数组的对比,/*行指针,其变化是行方向的地址变化*/ /*指向第i行*/ /*注意:*p仍然是地址,该语句输入从这个地址开始到0结束的那一串字符*/,输出结果: abcde abc abcd ab abcdef ab,47,#include void main() char *a5=“abcde“,“abc“,“abcd“,“ab“,“abcdef“; char *p; int i; for(i=0;i5;i+) p=a+i; printf(“%sn”,*p); p=a+2; p+; printf(“*p=%cn“,*p); ,读程序,a,/*定义一维指针数组a,a有五个数组元素,每个元素存字符串的首地址*/ /*二级指针*/ /* p指向指针数组a的每一个元素*/ /*注意:*p与pi等价,仍然是地址*/,输出结果: abcde abc abcd ab abcdef ab,48,相关语法:指针数组,元素均为指针类型数据的数组,称为指针数组 定义形式为: 类型关键字 *数组名数组长度; 例如 char *a5; 含义:,注意与行指针的区别: char (*a)5;,49,例9:字符串排序 方法一:用二维数组解决,char strN10 = “Pascal“,“Basic“,“Fortran“, “Java“,“Visual C“; for (i=0; iN-1; i+) /*交换法排序*/ for (j = i+1; jN; j+) if (strcmp(strj, stri) 0) strcpy(temp,stri); strcpy(stri,strj); strcpy(strj,temp); /*交换的是每一对字符串*/ ,50,方法1排序前后,若顺序发生变化,交换每个字符。,请注意:这样的一维数组只是一个示意图,并不在内存中存在。,51,例: 方法二:用指针数组解决,char *ptrN = “Pascal“,“Basic“,“Fortran“, “Java“,“Visual C“; for (i=0; iN-1; i+) /*交换法排序*/ for (j = i+1; jN; j+) if (strcmp(ptrj, ptri) 0) temp = ptri; ptri = ptrj; ptrj = temp; /*交换的是地址*/ ,52,方法2排序前后,指针的好处之二: 提高效率!,若顺序发生变化,交换数组元素(地址)。,53,#include void ave(float (*p)3,int n); void main() int num; float score53=65,98,76,78,69,87, 67,68,81,80,65,98,64,83,79; printf(“please input number of student, I will tell you his average score:“); scanf(“%d“, ,例10:求某个学生的平均值,54,#include float *find(float(*pionter)4,int n); void main() float score53=65,98,76,78,69,87, 67,68,81,80,65,98,64,83,79; float *p; int i,m; printf(“Enter the number to be found:“); scanf(“%d“, ,输出某个学生的成绩,返回指针值的函数,55,小结3,二维数组与指针 二维数组与指针的关系 区
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- (5篇)市幼儿园教师学习省教育系统英模巡讲的得体会汇编
- 2025-2026学年北京版(新教材)二年级上册数学第六单元“倍的认识”强化训练试卷附参考答案
- 胆汁淤积性肝炎的护理
- 雨课堂学堂在线学堂云《仓储与配送管理实务(陕西财经职院)》单元测试考核答案
- 高一预防电信诈骗主题班会教案
- 中国纺织服装行业社会责任年度报告(2023-2024) Social Responsibility Report of China's Textile and Apparel Industry
- 2026年设备监理师之设备监理合同考试题库【培优b卷】
- 浙江国企招聘-2025杭州市临安区城市发展投资集团有限公司下属众诚咨询公司公开招聘工作人员4人历年真题汇编附答案解析
- 2025湖北宜昌市五峰土家族自治县招聘县城社区专职人员6人历年真题汇编附答案解析
- 2025吉林大学白求恩第一医院生殖中心产前诊断中心采血员招聘3人历年真题汇编附答案解析
- 床-轮椅转移操作质量及评分标准
- AQ 1020-2006 煤矿井下粉尘综合防治技术规范(正式版)
- 零部件试验报告模板
- MOOC 健美操-华中农业大学 中国大学慕课答案
- 全国初级注册安全工程师职业资格考试辅导教材安全生产法律法
- 大班科学《各种各样的飞机》教案
- 药店执业培训与职业道德
- 四川省南江县光雾山旅游发展最终策划方案
- (设计)年产10万吨醋酸工艺设计
- 普外科-临床重点专科建设项目自查总结报告
- 焊接工艺规程
评论
0/150
提交评论