内存单元的地址-指针程序设计.ppt_第1页
内存单元的地址-指针程序设计.ppt_第2页
内存单元的地址-指针程序设计.ppt_第3页
内存单元的地址-指针程序设计.ppt_第4页
内存单元的地址-指针程序设计.ppt_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

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

文档简介

高级语言程序设计 第7章 内存单元的地址 指针程序设计(3) 问题3 把学生信息按学号或姓名排序 (指针版) n 问题描述:设有批量的学生信息,包括学 号num,姓名name,成绩grade,请把 它们保存到内存中,并按学号或姓名进行 排序。 分析 n学号和姓名均为字符串,如果用数组存放,学 号信息比较规则,假如是10个字符组成,只需 定义数组 char num 11,但是对于姓名来说 ,长短不一,必须开辟比较宽的数组,如char name 20, 这样就造成了不必要的浪费。 nC语言允许直接用字符型指针指向一个字符串, 称为指针型字符串,因此多个同学的信息可以 定义一个字符型指针数组 我们必须回答下面这些问题 n如何定义指针型字符串 n如何给指针型字符串提供数据(赋值或输 入)(回顾:数组型字符串怎么赋值怎么 输入?) n如何定义字符型指针数组 指针型字符串的定义 n const char *namePtr=“zhangqiang”; n 注意namePtr指向的是常量字符串 n namePtr称为指针型字符串或者说指向字符串 的指针 n比较namePtr与 n char nameStr=“zhangqiang”; n有什么不同 n1)namePtr是一个指针变量,可以指向不同的字 符串,但nameStr一旦定义就不可以改变,是 常量 n2)指针变量namePtr在定义之后可以通过赋值语 句重新获得一个字符串的首地址 namePtr = “liping”;(正确) 但nameStr = “liping”;(错误) 3) 数组型字符串通过键盘输入一个 scanf(“%s”,nameStr); 但是指针型,如果没有为namePtr申请空间 scanf(“%s”,namePtr); 或gets (namePtr); 都是错误的, n当然可以用字符型指针指向一个字符型数 组 n如 char str20,*ptr; n ptr = str; n 再scanf(“%s”,ptr); n4)没有初始化的指针ptr,直接作为字符 串使用是错误的: n char *ptr; n ptr0 = a; ptr1 = b; ptr2 = c; ptr3 = 0; 是错误的 例1 字符串长度计算函数 nint myStrlen(const char *pStr) /实参可以 是一个数组名 n n int len=0; n for( ; *pStr!= 0; pStr+) n len+; return(len); n 例2 字符串拷贝函数 nvoid myStrcpy( char *dstStr, const char *srcStr) n while(*srcStr!=0) n n *dstStr+ = *srcStr+; n /*dstStr = *srcStr n /srcStr+; /dstStr+; n n *dstStr=0; n 字符指针数组 n字符串指针放在一起就构成了一个指针数组 nconst char *name10 = “ZhangQiang“,“LiHong“, “WangLi“,“ZhaoMing“,“QianJin “, “SunYang“,“XuLei“,“BaoFang“, “GuoLiang“,“XiaoXiong“ ; 思考题: n如果用基于指针的字符串构成的指针数组 对字符串排序,可否不交换字符串的内容 而只修改指向它的指针? 如何从键盘输入字符串给字符型指 针? n在程序中可以直接赋值给指针 n不能直接从键盘输入字符串给指针 n可以先输入给一个字符型数组 n再copy给指针所指向的空间,这个指针指 向的空间必需事先申请好。如果字符串的 长短事先不能确定空间该怎么申请? 动态申请内存空间 n在函数内部的自动变量,在函数调用时自 动分配内存,函数调用结束后自动撤销; n全局外部变量或静态局部/外部变量在编译 时静态分配内存。 n字符串长短不能确定就要动态分配内存 n操作系统加载的应用程序之后,将形成一 个专门服务于该应用程序的内存空间(也 叫进程空间) n自动分配的内存分配在栈区,静态分配的 内存位于全局数据区,动态分配的内存位 于堆区。 n 动态分配内存函数 nC语言stdlib.h库接口的一部分或者用 malloc.h包括: malloc、calloc、realloc 和free nmalloc函数:分配长度为size的连续内存 空间,其原型为 void *malloc(unsigned int size); n(2)free函数:释放动态申请的空间, 其原型为 free(void *p); 动态申请的空间用毕之后必须调用free函 数把它释放,供系统重新分配。 n(3)calloc函数:为同类型数据分配连续的内存空间 ,其原型为: void *calloc(unsigned int num, unsigned int size); 其中num是要申请的内存空间的数量,size是每个空 间的字节数。 n n(4) realloc函数:改变已经分配的空间的 大小,其原型为 void * realloc(void *p, unsigned int size); n把p所指向的空间大小改为size。 void* 类型的指针 n int a = 10; float x = 5.3; n int *aPtr = n float *xPtr = nvoid类型的指针可以指向任何其它类型的内存 n void *gp = aPtr; n也可以gp = xPtr; n但是对gp指针的引用是错误的,即 n*gp = 5; /错误的间接引用 n*gp=3.6; /错误的间接引用 n只有非void*类型的指针才可以使用间接 引用运算*。 nvoid*类型的指针只能起到保存指针的作 用。 malloc举例 n char *cPtr; n cPtr =(char*) malloc(10); n scanf(“%s”,cPtr); n printf(“%sn“,cPtr); n free(cPtr); 注意! nchar *cPtr; ncPtr=“hello”; /这时cPtr指向了静态的 “hello” ncPtr指向的空间由“hello”确定 n不能再用scanf(“%s”,cPtr); 通常的做法 n char nameStr20, *namePtr; n先读到字符型数组中,计算字符串的大小 n scanf(“%s“,nameStr); n int len=strlen(nameStr); n再申请相应的空间 n namePtr = (char *) malloc(len*sizeof(char); n然后再拷贝 n strcpy( namePtr, nameStr); n 或 namePtr=nameStr; n这样 namePtr就指向了nameStr 看一个例子 n#include n#include n#include n/#include nint main(void) n n const char *namePtr=“zhangqiang“; n puts(namePtr); n namePtr=“lksdjfklsdj“; n puts(namePtr); n /gets(namePtr); /err n char nameStr120,nameStr=“zhangqiang“; n char *p = nameStr1,*p2=nameStr; n puts(nameStr); n gets(p); n puts(p); n /nameStr=“lksdjfkld“; n strcpy(p,p2); n puts(nameStr); n gets(nameStr); n puts(nameStr); n char *namePtr2; n namePtr2 = (char *) malloc(strlen(nameStr)*sizeof(char); n /strcpy(namePtr2,nameStr); n namePtr2=nameStr; n puts(namePtr2); n return 0; n 同样还可以 n动态申请一维整型数据空间 7.5.3动态申请一维数组 n动态申请二维整型数据空间,用一个列指 针指向它。 7.5.4动态申请二维数组 n同理还可动态申请行指针的二维数组 略,大家自己研究一下,查查相关资料 让指针指向在函数中动态申请的内存 n在后续数据结构与算法的课程中常常有这 样的需求,即在主调函数中定义一个指针 变量,但不知道它该指向哪里,还不知道 它指向的内存空间,而是由另一个专门的 函数动态申请所需的空间,这样的函数该 如何实现呢?让我们看看下面的这个函数 是否可以达到我们的要求, 返回动态申请的指针 nint* funcReturnPtr(void) n n int *tmp; n tmp=(int*)malloc(sizeof(int); n return tmp; n /该指针指向的空间函数调用结束时没有自动释放 n /在主函数或其它地方中使用它不会出现非法访问 n n在主函数中定义 int *aptr = NULL; /注意aPtr没有指向任何地方 函数调用 aptr= func(); 之后,aptr便指向了堆中申请的空间, n但是,这种方法明显有局限性,如果有多 个动态指针需要返回就不能这样做了。 nvoid func(int *ptr) n n ptr=(int *)malloc(sizeof(int); n n设在主函数中有 n int *aptr = NULL; /注意aPtr没有指向任何地方 n函数调用 func(aptr); n能否使aptr指向在函数func中申请的内存空间呢? 使用二级指针参数返回动态申请的指针 例 注意: n *aptr=(int *)malloc(sizeof(int); n这里是把申请到的指针赋值给二级指针 aptr所指向的一级指针变量即实参的aptr n现在可以完整的实现开始给出的问题了 n n动态申请空间,输入原始数据 input n按学号或姓名字符串排序sort n输出排序结果 print n代码略 再介绍两个特别的问题 n 命令行参数 n C+的引用 命令行参数 n每个应用程序都是一个可执行程序,都是 可以看成在操作系统中运行的命令。 n到现在为止我们设计的main函数都是只 有void参数,实际上main函数也允许有 参数,但是它的参数个数和类型是不能随 便定义的。 大家知道下面的命令 ngcc -o test test.cpp 它有几个参数呢? n又如 dir /p /w DOS命令后面的选项用/表示,/p就是分页显 示文件目录,/w是按多列像窗口一样显示文 件目录。 ncopy test.cpp testbak.cpp 那么main函数的参数是什么样子的呢? nmain函数的参数只有两个 n第一个形参是整型的简单变量,其名字规 定为argc(arg是参数argment的缩写,c 是count的意思), n第二个形参就是我们刚刚学过的字符型指 针数组,其名字规定为argv(v是向量 vector的意思,argv就是所有的参数构成 一列,含应用程序名字)。 n有参数的main函数的具体形式如下: n int main(int argc, char *argv) n这两个参数的具体含义是什么呢?先来看 看怎么样调用main函数,怎么给实参的 。 应用程序名 参数1 参数2 参数3 等等 命令行参数。 n应用程序名,参数1,参数2,参数3, 构成 了第二个实参传给argv,即字符型指针数组, n命令行中字符串个数就是第一个实参传给 argc C+中的引用 n 二级指针的方法实现上一小节的需求比较 容易出错,不易理解。 nC+编译器提供了一种引用传递方式。什 么是引用

温馨提示

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

评论

0/150

提交评论