c语言程序设计17第十七讲(第七章中).ppt_第1页
c语言程序设计17第十七讲(第七章中).ppt_第2页
c语言程序设计17第十七讲(第七章中).ppt_第3页
c语言程序设计17第十七讲(第七章中).ppt_第4页
c语言程序设计17第十七讲(第七章中).ppt_第5页
已阅读5页,还剩47页未读 继续免费阅读

下载本文档

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

文档简介

1,当我们开始编程时,就惊奇的发现要让程序正确运转比想象的要难。我们不得不使用调试技术。我还清楚地记得那一刻,从那时开始我就领悟到,从我自己的程序里寻找错误将成为我生活中的一个重要组成部分。 Maurice Wilkes,2,高级语言程序设计,主讲教师:贾彩燕 计算机与信息技术学院 计算机科学与技术系 ,3,课程内容,第一章 程序设计和C语言 第二章 数据对象与计算 第三章 变量、函数和控制结构 第四章 基本程序设计技术 第五章 C程序结构(函数) 第六章 数组 第七章 指针 第八章 文件和输入输出 第九章 结构和其它数据机制 第十章 程序开发技术 第十一章 标准库,4,数组的概念、定义和使用 数组程序实例 数组作为函数参数 字符数组和字符串 两维和多维数组 编程实例,第六章:数组,一维数值型数组的重要应用,5,作业提示,Squeeze(char s1, char s2),从字符串s1中删除所有出现在串s2中的字符。 自学6.6.4节(P208)统计C程序里的关键字,完成实现相关程序 如何得到输入? 如何取到关键字? 取到关键字后如何与关键字表进行对比统计? 魔幻方阵算法(从左下向右上放数) 先把1放在第一行的中间位置。 下一个数放在上一个数的右上方 若右上方已超出方阵的第一行,则下一个数放在该列的最后一行上。 若右上方已超出方阵的最后一列,则下一个数放在该行的第一列上。 若右上方已有数或右上方已超出方阵的第一行和最后一列,则下一个数放在上一个数的正下方。,6,for(i=0;i(n-1) i=i+2;j=j-1; else if(i(n-1)j=0; /判断右上方是否有元素 if(aij=0)aij=k; else i=i+2;j=j-1; aij=k; for(i=0;in;i+) for(j=0;jn;j+) printf(“%5d“,aij); putchar(n);,7,地址与指针 指针变量的定义和使用 指针与数组 指针数组 多维数组作为参数的通用函数 动态存储管理 定义类型 指向函数的指针,第七章 指针,8,要点回顾,如何定义一个指针变量? 指针变量在使用时为什么一定要指定指向的数据类型? 指针变量在使用时为什么一定要初始化? 未经初始化的指针变量称为? 指针变量上的两种主要操作是什么? 变量的两种访问方式是什么? 指针变量做函数参数时传递的是什么? 通过使用指针变量做为函数参数可以返回多于一返回值 改变函数调用时的环境变量 空指针有什么用?,9,地址与指针 指针变量的定义和使用 指针与数组 指针数组 多维数组作为参数的通用函数 动态存储管理 定义类型 指向函数的指针,第七章 指针,指针(数值型/字符型)与一维数组 (数值型数组/字符串)的关系,10,7.3 指针与数组,C指针与数组关系密切,以指针为媒介可以完成各种数组操作 用指针做数组操作同样要特别注意越界错误。 指针和数组的关系是C语言特有的,除了由C派生出的语言(如C+),一般语言中没有这种关系。 如何利用指针访问数组。,11,int *p1, *p2, *p3, *p4; int a10 = 1,2,3,4,5,6,7,8,9,10;,指向数组元素的指针,可以写: p1 = ,这个地址存在,但写 *p4 是错误的。P4没有指向合法元素,p1 = ,数组名是表示数组首地址的地址常量,区别?,12,当指针p指向数组元素时说p指到了数组里。这时由p可以访问被p指的元素,还可访问数组的其他元素。 例:p1 = &a0 , 则 p1+1合法,为a1的地址 p1+2、p1+3、也合法,分别为a2 、a3的地址,使用: *(p1 + 2) = 3;/* 给a2赋值 */ p2 = p1 + 5; /* 使p2指向a5 */ *(p2 + 2) = 5; /* 给a7赋值 */ *(p2 - 2) = 4; /* 给a3赋值 */ p2 = p2 - 2; /* 这使p2改指向a3 */,通过指针访问数组元素时必须保证不越界。,指针运算,13,指针运算原理 一个指针指向某数组里的元素时,为什么能算出下一元素位置?(这是指针运算的基础) 指针有指向类型,p指向数组a时,由于p的指向类型与a的元素类型一致,数据对象的大小可以确定。 p+1的值可根据p的值和数组元素大小算出。由一个数组元素位置可以算出下一元素位置,或几个元素之后的元素位置。指针运算的基础。,通用指针即使指到数组里,因没有确定指向类型,因此不能做一般指针计算,只能做指针比较。,14,可进行增/减量操作(指针应指在数组里): p3 = p2; +p3; -p2; p3 += 2; 如果两指针指在同一个数组里,可以求差,得到它们间的数组 元素个数(带符号整数)。 n = p3 p2; /* 也可以求 p2 p3 */ 在同一个数组里的指针可以比较大小: if (p3 p2) 当p3所指的元素在p2所指的元素之后时条件成立(值为1),否则不成立(值为0)。两个指针不指在同一数组里时,比较大小没有意义。,其他常用指针运算:,15,两个同类型指针可用 = 和 != 比较相等或不等; 任何指针都能与通用指针比较相等或不等; 任何指针可与空指针值(0或NULL)比较相等或不等 两指针指向同一数据元素,或同为空值时它们相等。,当一个指针指向数组时的数组写法与指针写法:指针的两种用法,设p1 = 相当于*(p3+2)=8;或 a7=8; p13称为数组写法,*(p1+3)称为指针写法 两类写法有等价效力,可以自由选用。,16, 变址运算符 ai *(a+i),ai pi *(p+i) *(a+i),17,对数组名求值得到指向数组首元素的指针值 数组名可以“看作”常量指针,可参与一些指针运算,与其他指针比大小,比较相等与不相等。 通过数组名的元素访问也可以采用指针写法。 a3可写为*(a+3)。 注意:数组名不是指针变量,特别是不能赋值,不能更改。 若a为数组,下面操作都是错误的: a+; a += 3; a = p; 有些运算虽不赋值但也可能没意义。如 a3 不可能得到合法指针值,因其结果超出数组界限,18,int main() int a5, *pa, i; for (i = 0; i 5; i+) ai = i + 1; pa = a; for (i = 0; i 5; i+) printf(“*(pa+%d):%dn“, i, *(pa+i); /通过指针找地址法 for (i = 0; i 5; i+) printf(“*(a+%d):%dn“, i, *(a+i); /通过指针找地址法 for(i = 0; i 5; i+) printf(“pa%d:%dn“, i, pai); /下标法 for (i = 0; i 5; i+) printf(“a%d:%dn“, i, ai); /下标法 return 0; ,例 数组元素的引用方法(1),19,/指针法 int main() int a10; int *p, i; for (i = 0; i 10; i+) scanf(“%d”, ,例 数组元素的引用方法(2),三种方法的比较: 下标法和地址法的执行效率相同,都是先计算数组元素的地址,再访问数组元素的值,费时。 指针法利用指针变量直接访问数组元素的值,不必计算数组元素的地址,执行效率高。 下标法直观,指针法与地址法不够直观。,20,基于指针的数组程序设计 指针运算是处理数组元素的一种有效方式。设有int数组a和指针p1,p2,下面代码都打印a的元素:,for (p1 = a; p1 a+10; +p1) printf(“%dn“, *p1); for (p1 = a; p1 - a 10; +p1) printf(“%dn“, *p1); for (p1 = a, p2 = a+10; p1 p2; +p1) printf(“%dn“, *p1); for (p1 = p2 = a; p1 - p2 10; +p1) printf(“%dn“, *p1);,21,数组参数的意义 C规定,数组参数就是相应类型的指针参数: int f(int n, int d) . . 和 int f(int n, int *d) . . 意义相同。,数组参数就是利用指针实现的! 这也使采用数组参数的函数能修改实参数组。,22,函数里也可用指针方式做元素访问。 int intsum (int n, int a) int i, m = 0; for (i = 0; i n; +i) m += *(a+i); return m; ,函数里不能用sizeof确定数组实参大小:函数的数组形参实际是指针,求sizeof算出的是指针的大小。 另一方面,sizeof的计算是在编译中完成的。实参是动态运行中确定的东西。,m+=ai;,int intsum (int n, int *a) int i, m = 0; for (i = 0; i n; +i) m += *(a+i); return m; ,23,使用数组的一段元素 以数组为参数的函数可处理一段元素。求元素和: double sum(int n, double a); 设有双精度数组b,40个元素已有值:,用sum可求b所有元素之和/前一段元素之和: x = sum(40, b); y = sum(20, b); sum不知道b的大小,它由参数得到数组首元素地址,从这里开始求连续40或20个元素的和。 也可用sum求b中下标12到24的一段元素之和。 z = sum(13, b+12);,24,例1 下面的程序的输出结果是什么? #include int a = 2,4,7,8,9; int main() int i,*p = a; for (i = 0; i 4; i+) ai = *(+p); printf(“%dn“, a2); return 0; ,运行结果为:8,25,例2 int a = 1,2,3,4,5,6,7,8,9,10, *p = a, i; 数组元素地址的正确表示: (A)&(a+1) (B)a+ (C)&p (D)&pi,数组名是地址常量 p+,p- () a+,a- () a+1, *(a+2) (),26,例 int main() int a = 5,8,7,6,2,7,3; int y, *p = ,输出:5 6,6,例3 注意指针变量的运算,*p+ *(p+) *p+、*+p、(*p)+作用不同 *p+先取p指向变量的值再指针变量加1 *+p先使指针变量加1再取*p (*p)+使p指向的元素值加1,27,int main() int i, *p ,a7; p = a; for (i = 0; i 7; i+) scanf(“%d“, p+); printf(“n“); for (i = 0; i 7; i+, p+) printf(“%d“, *p); return 0; ,p = a;,指针变量可以指到数组后的内存单元,例4 注意指针的当前值,28,要点:,1、指针变量可以实现自身值的改变: 如:p+; 但数组名则不能进行改变:a+是错误的用法。 2、应注意指针变量的当前值。 3、指针变量可以指向数组以后的内存单元。 4、注意以下的指针运算: 若:int a10,*p = a; 则:p+ 等价于 &a1 *p+ 等价于 *(p+) 但 *(p+)与*(+p)却不同 (*p)+等价于 a0+,29,例1 利用指针,输出int数组里一段元素: void prt_seq(int *begin, int *end) for (; begin != end; +begin) printf(“%dn“, *begin); ,prt_seq(a, a+10); prt_seq(a+5, a+10); prt_seq(a, a+3); prt_seq(a+2, a+6); prt_seq(a+4, a+4); prt_seq(a+10, a+10); 最后两个调用对应空序列。,完备吗?,30,“设置”函数: void set_seq(int *b, int *e, int v) for (; b != e; +b) *b = v; ,把序列中每个元素都用其平方根取代: void sqrt_seq (double *b, double *e) for (; b!=e; +b) *b = sqrt(*b); ,求平均值: double avrg(double *b, double *e) double *p, x = 0.0; if (b = e) return 0.0; for (p = b; p != e; +p) x += *p; return x / (e - b); ,31,数组名作函数参数,是地址传递 数组名作函数参数,实参与形参的对应关系,数组名作函数参数,32,实参与形参均用数组,void inv(int x, int n) int t, i, j, m = (n-1)/2; for (i = 0; i = m; i+) j = n-1-i; t = xi; xi = xj; xj = t; int main() int i, a10 = 3,7,9,11,0,6,7,5,4,2; inv(a, 10); printf(“The array has been reverted:n“); for (i = 0; i 10; i+) printf(“%d,“, ai); printf(“n“); return 0; ,m=4,例5 将数组a中的n个整数按相反顺序存放(1),33,void inv(int *x, int n) int t,*p,*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; int main() int i,a10 = 3,7,9,11,0,6,7,5,4,2; inv(a, 10); printf(“The array has been reverted:n“); for (i = 0; i 10; i+) printf(“%d,“, ai); printf(“n“); return 0; ,实参用数组,形参用指针变量,例5 将数组a中的n个整数按相反顺序存放(2),34,void inv(int *x, int n) int t,*i,*j,*p,m=(n-1)/2; i=x; j=x+n-1; p=x+m; for(;i=p;i+,j-) t=*i; *i=*j; *j=t; int main() int i, a10, *p = a; for (i = 0; i 10; i+, p+) scanf(“%d“, p); p=a; inv(p, 10); printf(“The array has been reverted:n“); for (p = a; p a+10; p+) printf(“%d“, *p); return 0; ,实参与形参均 用指针变量,例5 将数组a中的n个整数按相反顺序存放(3),35,void inv(int x, int n) int t, i, j, m = (n-1)/2; for (i = 0;i = m; i+) j = n-1-i; t = xi; xi = xj; xj = t; int main() int i, a10, *p = a; for (i = 0; i 10; i+, p+) scanf(“%d“, p); p = a; inv(p, 10); printf(“The array has been reverted:n“); for (p = a; p a+10; p+) printf(“%d “, *p); return 0; ,实参用指针变量 形参用数组,例5 将数组a中的n个整数按相反顺序存放(4),36,#include #define MAX 5 void fun1(); void fun2(int ); int aMAX; int main() fun1(); fun2(a); printf(“n“); return 0; void fun1() int k, t = 0; for (k = 0; k MAX; k+, t+) ak = t+t; void fun2(int b) int k; for (k = 0; k MAX; k += 2) printf(“%4d“, *(b+k); ,例6 分析程序写出结果,运行结果为:0 4 8,37,#include void fun(int *s) static int j = 0; do sj += sj+1; while(+j 2); int main() int k, a10 = 1,2,3,4,5; for (k = 1; k 3; k+) fun(a); for (k = 0; k 5; k+) printf(“%4d”, ak); return 0; ,例7 分析程序写出结果,运行结果为:3 5 7 4 5,38,int *p 与 int q10 数组名是指针(地址)常量 p = q; p+i 是qi的地址 数组元素的表示方法:下标法和指针法, 即若p=q, 则 pi qi *(p+i) *(q+i) 形参数组实质上是指针变量,即int q int *q 在定义指针变量(不是形参)时,不能把int *p 写成int p; 系统只给p分配能保存一个指针值的内存区(一般2字节);而给q分配sizeof(int)*10字节的内存区,一级指针变量与一维数组的关系,39,定义字符指针时可用字符串常量初始化,如: char *p = “Programming“; 1)定义了指针p 2)建立了一个字符串常量,内容为“Programming“ 3)令p指向该字符串常量。图(a) char a = “Programming“; 1)定义了一个12个字符元素的数组 2)用“Programming“各字符初始化a的元素,图(b),字符指针与字符数组,常用字符指针指向字符数组元素,40,1)指针p可重新赋值(数组不能赋值:a=“” ): p = “Programming Language C“; 2)p和a类型不同,大小不同。a占12个字符的空间。 3)a的元素可以重新赋值。如: a8=e; a9=r; a10=0; a的内容现在变成“Programmer”,41,/字符串用字符数组实现 int main( ) char string = “I love China!”; printf(“%sn”, string); printf(“%sn”, string+7); return 0; ,/字符串用字符指针实现 int main( ) char *string = “I love China!”; printf(“%sn”, string); string += 7; while (*string) putchar(string0); string+; return 0; ,I love China! China!,42,#include int main() char arr = “ABCDE“; char *ptr; for(ptr = arr; ptr arr+5; ptr+) printf(“%sn“, ptr); return 0; ,运行结果:ABCDE BCDE CDE DE E,例1 分析以下程序的运行结果,43,#include int main() char *p1 = “programming“, *p2 = “language“; int i; for (i = 0; i 7; i+) if (*(p1+i) = *(p2+i) printf(“%c“, *(p1+i); return 0; ,运行结果:ga,例2 分析以下程序的运行结果,44,例3,输入一行到数组里:,enum NLINE = 256 ; char lineNLINE; int count; char *p; /*-*/ p = line; while(plineNLINE-1 /* 统计e的个数 */,45,例1,用指针方式实现字符串长度函数。一种方式: int strLength (const char *s) int n = 0; /*通过局部指针扫描串中字符*/ while (*s != 0) s+; n+; return n; ,另一实现: int strLength (const char *s) char *p = s; while (*p != 0) p+; return p - s; ,参数类型(char*),实参应是字符串或存字符串的数组,指针与数组操作函数实例,指针使用非常灵活,46,void strCopy(char *s, const char *t) while (*s = *t) != 0) s+; t+; ,把指针更新操作也写在循环测试条件里, void strCopy (char *s, const char *t) while (*s+ = *t+) ; / 空语句 ,赋值表达式有值,0就是0,可简化: void strCopy(char *s, const char *t) while(*s = *t) s+; t+; ,例2,用指针实现字符串复制函数。,47,例 用函数调用实现字符串复制,(1)用字符数组作参数,void copy_string(char from,char to) int i = 0; while (fromi != 0) toi = fromi; i+; toi = 0; int main() char a = “I am a teacher.“; char b = “You are a student.“; printf(“string_a=%sn string_b=%sn“, a, b); copy_string(a, b); printf(“nstring_a=%snstring_b=%sn“, a, b); return 0; ,字符指针作函数参数,48,例 用函数调用实现字符串复制,(2)用字符指针变量作参数,void copy_string(char *from, char *to) for (; *from != 0; from+, to+) *to = *from; *to = 0; int main() char a = “I am a teacher.“; char b = “You are a student.“; pri

温馨提示

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

评论

0/150

提交评论