课件计算概论Lecture 16_第1页
课件计算概论Lecture 16_第2页
课件计算概论Lecture 16_第3页
课件计算概论Lecture 16_第4页
课件计算概论Lecture 16_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

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

文档简介

1、计算概论(Introduction to Computing),主讲人:马思伟 北京大学数字媒体研究所 ,第十六讲 指针,指针变量的定义,int c = 76;/定义int型变量c,并赋值76; int *pointer; /定义名字为pointer的指针变量; /“*”表示变量pointer的类型为指针类型; pointer = /将变量c的地址赋值给指针变量pointer; /赋值后,称指针变量pointer指向了变量c,指针变量的使用,则*pointer: 为“pointer所指向的存储单元的内容”; “pointer所指向的存储单元的内容” 是 变量c,若有:,0 x0012FF74

2、0 x0012FF75 0 x0012FF76 0 x0012FF77 0 x0012FF78 0 x0012FF79 0 x0012FF7A 0 x0012FF7B,int c = 76;, ,0 x0012FF78,pointer,int c = 76; int *pointer = ,可以利用 指针运算符* 实现,指针变量的使用,正确的 int a=10; float b; int c10; int *p= ,程序举例,#include void main() int *p1, *p2, *p; int a, b; scanf(%d, %d“, ,动态数组 申请空间,用前面讲过用如下方法

3、可以定义一个数组: char name20; / 定义一个类型为char长度为20的数组。 在申请动态数组之前,先定义指向动态数组的指针。例如: char *name; 然后,用malloc()函数申请动态数组: name = (char *)malloc(20);,动态数组 头文件,使用前要在文件的开始包含文件。例如: #include void main( ) double *pd; pd = (double *)malloc(sizeof(double) * 50); ,动态数组 赋值,int *pi; pi = (int *)malloc(sizeof(int) * 100); /一百

4、个数组元素,每个元素类型为int *pi = 0; / 将数组的第1个元素赋值为0 *(pi+1) = 1; / 将数组的第2个元素赋值为1 *(pi+2) = 2; / 将数组的第3个元素赋值为2,动态数组 赋值,与静态数组相同,动态数组的元素下标也是从0开始的。所以对上面pi所指的数组可以用如下的循环将全部元素赋初值为0: int j; for(j=0; j100; j+) *(pi+j) = 0;,动态数组 空间回收,静态数组是数组变量定义时分配空间的,它的空间在该变量失效时由系统自动回收。 动态数组是用malloc()函数动态申请的,需要在程序中调用free()函数主动释放。如: ch

5、ar *pc; /定义字符指针pc pc = (int *)malloc(sizeof(char) * 2); / 两个数组元素,每个元素类型为char free(pc);,动态数组 注意事项,强制类型转换 malloc返回一个void *类型的地址,必须通过强制类型转换,才能赋值给特定的指针变量,如 int *pint = (int *) malloc(.); 使用sizeof() 最好使用“sizeof(类型名)*动态数组长度”形式确定分配内存的大小,如 int *pint = (int *) malloc(sizeof(int)*.); 分配的内存不再使用时一定要释放 free(pint

6、);,动态数组 注意事项,分配失败处理 malloc分配内存不能分配时,返回一个NULL值,可以根据返回值判断内存分配是否成功 int *pint = (int *)malloc(131);if (pint=NULL) printf(“Can not alloc so many memory!”); else printf(“A lot of memory are allocated!”); free(pint); ,提纲,内容 指针与数组 指针与字符串 要求 掌握用指针访问数组的方法 掌握指针地址操作,数组与指针,数组元素的存储 连续的内存单元,数组名为元素首地址 例: int a10; /

7、定义一个包含10个整型数据的数组 /假设a0的地址为1000, /即a=1000, 但不能对数组名进行赋值,内存单元,地址,数组与指针,指向数组元素的指针 例: int a10; /定义一个包含10个整型数据的数组 int *p; /定义一个指向整型变量的指针变量 p=,数组与指针,通过指针引用数组元素 地址偏移,取得相应元素的地址 p+i 和a+i就是ai的地址 p+1=1004不是1001! p+1所代表的地址实际上是 p+1*d, d表示一个数组元素所占的字节数 累加地址,p+ 取地址(指针)内容,获得相应的数组元素 *p, *(p+i),*(a+i)表示p+i, a+i所指向的数组元素

8、即ai, 可视为变址运算符,即按a+i计算地址,然后找出此地址单元的值 指向数组的指针变量也可以带下标,pi与*(p+i)等价 pi *(p+i),a0,a9,ai,数组与指针,通过指针引用数组元素 方法1:下标法,即ai 方法2:地址法,即*(a+i),相应于计算a+i*d地址 方法3:指针法,*p, pi, *(p+i) 方法比较:输出一个有10个整数元素的数组的值 指针法(*p)效率最高 数组名不允许进行a+运算,void main() for(i=0; i10; i+) printf(“%d “,ai); . ,void main() for(i=0; i10; i+) printf(

9、“%d “,*(a+i); . ,void main() int *p; for(p=a; p(a+10); p+) printf(“%d “,*p); . ,数组与指针,例:用指针输出a数组的10个元素,#include void main() int *p, i, a10; p=a; for(i=0; i10; i+) scanf(“%d”, p+); printf(“n”); for(i=0; i10; i+, p+) printf(“%d”, *p); printf(“n”); ,假设输入 1 2 3 4 5 6 7 8 9 10 输出是 1 2 3 4 5 6 7 8 9 10 ?

10、?,p,p=a;,数组与指针,关于指针地址运算 p+,指向下一元素地址,不是下一内存单元地址 *p+的运算顺序与*(p+)等价,是先*(p),然后p+, printf (“%d ”, *p+); *(p+)与*(+p)不同,前者先取*p,然后p加1,后者p先加1,再取*p printf (“%d”, *p+); printf (“%d ”, *(+p); 输出? +(*p)表示p所指向的元素值加1 printf(“%d ”, +(*p); 如果p指向数组a中第i个元素,*(p+)与ai+等价,*(+p)与a+i等价 其他 *(p-),*(-p),(*p)-,a0,a9,p,ai,数组与指针,关

11、于地址运算 两个指针变量相加无意义 float scores10; float *pscore1 = scores; float *pscore2 = scores+1; pscore1+pscore2; 错! 两个指针变量相减是其间的元素数目 (pscore2-pscore1) = = 1; 同类型指针变量可比较大小(地址值的大小) (pscore2pscore1); (pscore2pscore1); pscore2=scores;,习题,1:有以下语句,则对a数组引用不正确的是(0=i=9) int a10=0,1,2,3,4,5,6,7,8,9,*p=a; A) ap-a B) *(

12、int *p= 则b的值是( ) A) 5 B) 6 C) 9 D) 8 答案 C p5=*(p+5)=*(a+3)+5)=*(a+8)=a8,a0,a9,1000,1004,1008,1012,1016,1020,1024,1028,1032,1036,p, int *p; for (p=val0; pval0+12; p+) if (p-val0)%4=0) printf(“n”); printf(“%4d”, *p); printf(“n”); ,数组与指针,例:用指针变量将一个数组中的整数按相反顺序存放,#include void main() int arr10=3, 7, 9, 1

13、1, 0, 6, 7, 5, 4, 2; int *pi = arr; int *pj = arr+9; int t; for(; pipj; pi+, pj-) t = *pi; *pi = *pj; *pj = t; return 0; ,arr,arr+m,n-1-i,arr+n-1-i,数组元素下标,数组元素指针,字符串与指针,字符指针与字符串 字符指针赋值 char *str=“Beijing”; /字符串常量编译后即分配空间存储 printf(“%s”, str); 或 char *str; str=“Beijing”; /字符串常量编译后即分配空间存储 printf(“%s”,

14、str); 或 char *str; char s15=“Beijing China”; str= s;,字符串变量输入,字符串变量初始化 定义时初始化 char s12 = “I am happy”; char *str=“I am happy”; 使用scanf(), gets()输入 char name12; char *str; scanf(“%s”, name); scanf(“%s”, str); str = name; scanf(“%s”, str); gets(name);,字符串变量输出,使用printf(), puts()输出 printf(“%s”, s); print

15、f(“%s”, str); puts(name);,字符串变量输出,例 #inlcude int main() char s12 = “I am happy”; char *str; str = s; *str = U; printf(“%sn”, str); str = s+5; printf(“%sn”, str); return 0; ,字符串操作,字符串复制 使用指针操作 #inlcude #inlcude int main() char s12 = “I am happy”; char t20; char *ps=s, *pt=t; for (; *ps!=0; ps+, pt+)

16、*pt = *ps; *pt = 0; printf(“%sn%s”, s, t); return 0; ,s,t,字符串操作,用指针处理,void main() char *a=“I love China”; a = a+7; printf(“%s”, a) ,字符串应用,求字符串中大写字母的个数 #include int main() char str256, *ps; int count; scanf(“%s”, str); for (ps=str; *ps!=0; ps+) if (*ps=A ,字符串应用,比较两个字符串的大小,输入两个字符串,输出两个字符串比较的结果 #includ

17、e int main() char s1256, s2256; char *ps1=s1, ps2=s2; int cmp; scanf(“%s”, str); for (; *ps1=*ps2 ,字符串处理函数,strcat( char *dst,char *src):连接字符串 strcpy(char *dst,char *src):复制字符串 strcmp(char *str1,char *str2):比较字符串 strlen(char *str):求字符串长度 strlwr(char *str):把字符串中字符都变小写 strupr (char *str):把字符串中字符都变大写 #i

18、nlcude ,小结,使用指针访问数组 指针地址操作,作业,1. 使用指针进行两个字符串的连接操作 2. 使用指针将一个字符串进行逆序排列输出 3. 计概教材, P302, 2.(4)题,使用指针实现数组元素循环移动。,函数,传值调用与传地址调用,传地址调用的三种形式,方法一:使用指针 主调用函数的实参及被调用函数的形参都是指针 方法二:使用数组 主调用函数的实参及被调用函数的形参都是数组 方法三:数组/指针及指针/数组 主调用函数的实参及被调用函数的形参为指针或数组,传地址调用,void swap(int *a, int *b) int tmp=0; tmp = *a; *a = *b; *

19、b = tmp; ,void main( ) int a=0, b=0; a = 20; b = 45; if (ab) swap( ,传地址调用,45,20,传地址调用的三种形式,方法一:使用指针 主调用函数的实参及被调用函数的形参都是指针 方法二:使用数组 主调用函数的实参及被调用函数的形参都是数组 方法三:数组/指针及指针/数组 主调用函数的实参及被调用函数的形参为指针或数组,数组参数传递,数组元素作为函数实参,与变量用法相同,为传值调用 例1. 传递数组元素 两个数组a, b,各有10个元素,逐个元素进行比较,如果a中元素大于b中相应元素的数目多于b中元素大于a中相应元素的数目,则认为

20、a数组大于b数组。给定a,b判断二者间的关系 void main() int a10, b10; int i, m=0, n=0, k=0; for (i=0; ik) printf(“a is larger than b”); else if (nk) printf(“b is larger than a”); else printf(“a and b is equal”); ,int larger (int x, int y) if (xy) return 1; else if (xy) return -1; else return 0; ,数组参数传递,数组名可以作为实参和形参传递,传递

21、的是数组首元素的地址,相应的形式参数应当为数组名或指针变量 例, 有一个一维数组,内放10个学生成绩,求平均成绩 void main float average(float array, int n); float score10; float aver; . aver = average(score, 10); printf(“average score is %f”, aver); float average(float array, int n) . ,数组参数传递,数组名作为参数传递 应在主调用函数和被调用函数中分别定义数组 实参数组与形参数组类型应一致(类型不一样会如何?) 形参数组的大小不起任何作用,可以不指定,也可以根据需要传送一个数组大

温馨提示

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

评论

0/150

提交评论