欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    第五章构造数据类型.ppt

    • 资源ID:5665911       资源大小:2.09MB        全文页数:126页
    • 资源格式: PPT        下载积分:10金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要10金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    第五章构造数据类型.ppt

    第五章 构造数据类型,C+开发实例教程刘畅主编 电子工业出版社,本章学习内容,掌握数组的概念以及应用;理解指针的概念,掌握指针的使用;掌握指针与数组的区别,能够使用多重指针以及指针与数组的多种混合体,会分配动态数组;掌握常用的字符串处理函数;理解引用的概念,掌握引用型函数参数的用法;掌握结构与联合类型的定义与应用,并注意二者之间的区别;掌握枚举数据类型的使用。,本章目录,第十一讲 数 组第十二讲 指针基础知识第十三讲 字符指针、指针数组、指向指针的指针和常用字符串处理函数第十四讲 指针和函数第十五讲 动态存储分配、void指针和引用第十六讲 结构、联合与枚举类型本章小结,结 束,第十一讲 数 组,一、一维数组的定义、初始化、数据赋值、数组越界二、二维数组三、数组作为函数参数练一练,返回本章目录,一、一维数组的定义、初始化、数据赋值、数组越界,【实例5-1】将学生成绩从大到小排序(学生成绩由数组初始化得到,使用冒泡法进行排序)。点击打开【实例5-1】源程序。程序运行结果如下:,返回本讲目录,1一维数组的定义,一维数组定义的一般形式为:其中:(1)数据类型为数组元素的数据类型,可以由基本的数据类型进行定义,例如整型、浮点型等基本类型,也可以是结构、类等用户自定义类型(后面介绍),但void类型除外。(2)数组名为数组的名称,必须遵循标识符的命名规则,同一函数中的数组名不能与其他变量同名。,数据类型 数组名常量表达式;,返回本讲目录,(3)常量表达式为一维数组中存储的元素的个数,可以为常量或符号常量,必须是正整数,表示数组的大小或长度,不能为变量。(4)方括号“”是数组下标运算符,在数组定义时用来限定数组元素的个数。数组名是一个地址常量,不能作为赋值的目标。因此,不能将一个数组整体赋值给另外一个数组。,返回本讲目录,2数组初始化,数组的初始化就是在声明数组时给部分或全部元素赋初值。一维数组初始化的一般形式为:,数据类型 数组名常量表达式=初值1,初值2,初值n;初值表,返回本讲目录,(1)其中初值1,初值2,初值n称为初值表,初值之间用逗号分隔。例如,定义了5个元素的整型数组a的语句如下:int a5=1,2,3,4,5;(2)当对全部数组元素赋初值时,可以省略数组的大小,此时数组的实际大小就是初值列表中初值的个数。例如,定义具有5个元素的字符数组c的语句如下:char c=a,b,c,d,e;(3)可以只给数组中部分元素赋初值。int a10=1,2,3,4,5;,返回本讲目录,3数组引用,一维数组元素引用的一般格式为:对一维数组的两点说明:(1)下标表达式可以是变量表达式,用来标识数组元素。(2)C+中数组的下标从0开始,若数组中元素个数为n,则数组的下标依次为0,1,2,3,n-1,对应的数组元素依次为a0,a1,an-1。例如,在【实例5-1】中第17行语句:t=ai;中的ai就是对数组a中第i个元素的引用。,数组名下标表达式,返回本讲目录,4数组越界,C+中,编译和执行时并不检查数组下标是否越界。例如,如果有int a10;语句,则该一维数组a中元素的最大下标值为9,若在程序中引用数组元素时使用a10则数组越界。但是在编译和执行时并不能检查出这种错误。这是因为数组的名字即为数组的首地址,a10对应于内存地址a+10,但是此地址可能不在程序可以控制的范围内,由此带来的非法内存地址访问可能会对系统或程序产生不可预知的影响。所以,使用数组时需要特别注意检查下标是否越界。,返回本讲目录,二、二维数组,【实例5-2】有一个34的矩阵,求其中元素的最大值,以及该元素所在的行号和列号。点击打开【实例5-2】源程序。(1)定义二维数组int a34,定义变量max存放最大值,变量row存放最大值的行号,变量col存放最大值的列号;(2)将第一个元素a00作为临时最大值max,row和col的初值设为0;(3)将max与每一个元素aij进行比较,若aijmax,把aij作为新的临时最大值,并将其下标i和j赋给row和col;(4)当全部元素比较完后,max是整个矩阵全部元素的最大值,输出最大值max和其所在的行号row和列号col。程序运行结果如下:,返回本讲目录,5二维数组,当数组元素的下标有两个或两个以上时,称该数组为多维数组。下标为两个时,称为二维数组;下标为三个时,称为三维数组;以此类推,下面我们主要介绍一下二维数组。(1)二维数组定义的一般格式为:说明:常量表达式1是数组元素的行数,常量表达式2是数组元素的列数。,数据类型 数组名常量表达式1常量表达式;,返回本讲目录,(2)二维数组的初始化:二维数组的初始化与一维数组初始化方法相似,初值表有两种形式:嵌套的初值表和线性初值表。嵌套初值表例子如下所示:int a23=1,2,3,4,5,6;/a数组分行初始化int a23=1,2,3,4,5,6;/a数组不分行初始化int a23=1,2,4;/对二维数组a部分元素初始化int a3=1,2,3,4,5,6;/省略第一维的数组长度,返回本讲目录,(2)二维数组的初始化:线性初值表例子如下所示:int a23=1,2,3,4,5,6;/初始化了全部数组元素int a23=1,2,3;/初始化了部分数组元素int a3=1,2,3,4,5,6;/初始化了全部数组元素,此时可以省略第一维数组的长度当使用线性初值表省略第一维元素个数时,该值计算方法为:向上取整(线性初值表项数/第二维元素个数)例如:int a3=1,0,0,0;则第一维元素个数为4/3=2。,返回本讲目录,(3)二维数组元素引用的一般格式:说明:行下标表达式与列下标表达式的值同样从0开始,如果有一个二维数组行数为m,列数为n,则行下标范围为0m-1,列下标范围为0n-1。如第i行、第j列的元素可表示成为aij。,数组名行下标表达式列下标表达式,返回本讲目录,三、数组作为函数参数,【实例5-3】设计一个函数,计算二维数组每行元素值的和。).点击打开【实例5-3】源程序。程序分析:在主函数中初始化一个二维数组并将每个元素都输出,然后调用子函数RowSum()计算每一行的元素之和,将和直接存放在每行的第一个元素中,返回主函数之后输出各行元素的和。程序运行结果如下:,返回本讲目录,6数组作为函数参数,数组名是一个地址,它可以作为函数的形参,接收实参传送来的地址,当形参接收实参传送来的地址后,形参数组与实参共享内存中的存储空间,形参值改变将影响实参的值。数组作为形式参数时,函数调用时传递的是地址。所以,形式参数中数组的大小没有意义,可以省略。,返回本讲目录,关于数组作为函数参数的几点说明:(1)用数组名作函数参数,应该在主调函数和被调用函数中分别定义数组。例如,在【实例5-3】中table是实参数组名,a是形参数组名。且数据类型必须一致,否则结果将出错。(2)用数组名作函数实参时,不是把数组元素的值传递给形参,而是把实参数组的起始地址传递给形参数组,这样两个数组就共占同一段内存单元。(3)C+编译系统对形参数组大小不做检查,所以形参数组可以指定大小也可以不指定大小。,返回本讲目录,练一练,【练习5-1】有一个34的矩阵,调用函数求所有元素中的最大值。解:定义一个子函数fmax,在子函数fmax中设一个最大值max,并赋初值为arr00,然后将arrij与max进行比较,如果arrijmax,则将arrij赋给max,最后返回max值即为该数组中元素的最大值。注意在调用该函数时是将数组名作为函数参数传递的,此时是将实参数组名a(数组首地址)传给形参数组名arr,即两个数组是同一个数组。,点击打开【练习5-1】源程序。,程序运行结果如下:,返回本讲目录,第十二讲 指针基础知识,一、指针的定义、初始化、运算及const指针二、一维、二维数组中的指针使用三、指向一维数组的指针 练一练,返回本章目录,一、指针的定义、初始化、运算及const指针,【实例5-4】阅读下面程序,分析并写出程序的运行结果。点击打开【实例5-4】源程序。程序运行结果如下:,返回本讲目录,程序分析:程序中首先定义了一个整型变量i并初始化为10,接着定义了一个整型指针ip,然后用取地址操作符“&”求出i的地址并赋给指针ip。此时,变量i中存放的是整数10,指针ip中存放的是地址3000,如图5-1所示。(这里假设整型变量i和整型指针ip在内存中的地址分别为3000和2000。)输出流中的*ip即指针ip所指的变量i的值(为10)。这时,输出的i值和*ip都是10。前者是直接访问,后者是通过指针的间接访问。直接输出ip的值表示指针ip所指的变量i所在的内存地址值。,图5-1【实例5-4】内存变量地址及指针示意图,返回本讲目录,1指针定义,当定义一个变量后,内存中将会划出一块由若干个存储单元组成的区域,用于保存该变量的数据。在内存里每个存储单元都有各自的编号,称为地址。在C+中,提供了指针类型,它是一种用于存放内存单元地址的变量类型,地址就存储在这种指针类型的变量中。由于指针变量存储的是地址,用它来指明内存单元,所以形象地称这种地址变量为指针。,返回本讲目录,返回本讲目录,指针定义的一般格式:说明:数据类型是指针变量所指向对象的数据类型,它可以是基本数据类型,也可以是构造数据类型以及void类型。指针变量名是用户自定义的标志符。星号“*”表示定义的变量是一个指针变量,而不是普通变量。,数据类型*指针变量名;,如果指针指向的是一种不确定的数据类型,则可以用void进行定义。,返回本讲目录,2指针的初始化,(1)在定义指针的同时进行初始化:例如:int i=10;/定义一个整型变量i int*ip1=/将变量i的地址赋值给指针变量ip1由于ip1是一个指针,所以不能将变量i的值直接赋值给ip1,只能将变量i的地址赋值给ip1。符号“&”是一个取地址运算符,可以得到变量的内存地址。,返回本讲目录,数据类型 幕*指针名=初始地址;,返回本讲目录,(2)在定义指针变量之后,单独使用赋值语句进行赋值:,指针名=地址;,例如:int*ip2=ip1;此时,这两个指针指向同一存储空间,如图5-2所示。,图5-2 两个指针指向同一个存储空间示意图,返回本讲目录,对于指针的几点说明:(1)指针赋值时类型必须一致,如果不一致要进行强制转换。例如:inta=10;int*p1=/正确,将整型指针强制转换成字符型后赋给字符指针p3(2)void类型的指针可以存储任何类型的地址,但是与其他类型进行赋值时要使用强制类型进行转换。例如:void*p1;int*p2=(int*)p1;,返回本讲目录,3指针运算,(1)“*”和“&”运算“*”称为指针运算符。它有两种含义:在定义指针变量时,例如:int*p;中的“*”起到说明作用,说明p是一个指针变量;当“*”出现在指针变量表达式左边时,表示访问指针所指对象的内容。其书写格式如下:,*指针变量表达式,返回本讲目录,(2)指针与整数的加、减运算指针的加、减运算与普通变量的加、减运算有所区别,指针变量中存放的是变量的内存地址,指针加上或减去一个整数n,表示指针从当前位置向后或向前移动n个sizeof(数据类型)长度的存储单元,如图5-3所示。例如:int*p,*q,a=5;p=/相当于*q=*p,q+,p+,返回本讲目录,(3)两指针相减当两个指针指向同一数组时,两个指针相减才有意义。两个指针相减表示两个指针之间数组元素的个数,结果为一个整数。(4)两个指针的比较运算主要进行以下处理:比较两个指针所指向的对象在内存中的位置关系。判断指针是否为空。,返回本讲目录,4const指针,(1)指针常量如果在定义指针变量时,指针变量前用const修饰,被定义的指针变量就变成了一个指针类型的常变量,指针类型的常变量简称为指针常量。格式如下:修饰符const与指针变量紧邻,说明指针变量不允许修改。既然指针变量的值不能修改,所以一定要在定义时给出初值。,数据类型*const 指针变量=变量名;,返回本讲目录,(2)常指针如果在定义指针变量时,数据类型前用const修饰,被定义的指针变量就是指向常量的指针变量,指向常量的指针变量称为常指针。格式如下:定义了一个常指针后,指针指向的值就不能被更改,即不能通过指针变量直接更改指针指向的值。,数据类型 const*指针变量=变量名;或 const 数据类型*指针变量=变量名;,定义常指针时不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外对象。,返回本讲目录,二、一维、二维数组中的指针使用,【实例5-5】分析下面程序,并写出程序的运行结果。点击打开【实例5-5】源程序。程序分析:在前面的章节中我们已经学习过一维数组、二维数组元素的输出,数组名就是数组的首地址,那么数组名就是指向数组第一个元素的指针,而*(a+i)中的a+i为数组首地址a加上i个元素的地址,得到的是数组中第i个元素的地址,再通过取对象运算*,得到对象*(a+i)就是数组a中各元素的值。依次输出数组a的各个元素。同理,当指针p=a;时,p也指向数组a的首地址,这时使用指针p也可以输出数组a中的各元素。使用方法与使用数组名a相同。*(p+i)也表示数组a中下标为i的元素。,返回本讲目录,返回本讲目录,b也是二维数组b的首地址指针,则(b+i)为二维数组的第i行首地址,取对象后*(b+i)得到该行第0个元素的首地址,然后*(b+i)+j再加上j得到该行第j个元素的地址,再取对象*(*(b+i)+j)就得到了该对象,即数组b中的每一个元素bij。依次输出数组b的各个元素。程序运行结果如下:,返回本讲目录,返回本讲目录,5指针与一维数组、二维数组,指针加减运算的特点使得指针特别适合于处理存储在一段连续内存空间中的同类型数据。而数组恰好是具有一定顺序关系的若干同类型变量的集合体,数组元素的存储在物理上也是连续的,数组名就是数组的首地址,这样我们就可以使用指针来对数组及其数据进行方便、快速的操作。,返回本讲目录,(1)一维数组的指针操作 一维数组的数组名实际上就是指向数组下标为0的元素的指针。,则数组a中的元素与数组名a及指针p的关系,如图5-4所示。指向一维数组首元素的任何指针也可以像一维数组名那样使用。由于指针p和数组名a均是指向数组a的首元素的指针,即p和a是完全等价的。因此,访问数组a中下标为i的元素,可以使用如下四种表示形式:ai、pi、*(a+i)、*(p+i)。,图5-4 一维数组元素与元素地址关系示意图,返回本讲目录,(2)二维数组的指针操作,图5-5 数组元素与元素地址关系图,二维数组b中bij的地址可以用以下5种表达式求得:&bij、bi+j、*(b+i)+j、&b00+列数*i+j、b0+列数*i+j。,返回本讲目录,三、指向一维数组的指针,【实例5-6】分析下面的程序,并写出程序的运行结果。程序分析:本程序通过两种指针方式输出一个二维数组。定义一个整型指针p和一个指向一维数组的指针pa。第一个循环使用了指向一维数组的指针pa,在外层循环中首先将二维数组a的首地址赋给指针pa,这时pa就指向了数组a的首地址。然后在内层循环中j为二维数组的列下标,输出对象*(*pa+j)(j从01变化即可输出该行的数组元素值),然后pa自增,相当于移到数组的下一行行首,继续输出,最后输出全部数组元素。,返回本讲目录,然后再将普通指针p指向数组的第0行的首地址,这时相当于p指向了a00元素,然后使用双重循环输出元素*(p+),即数组a的各元素的值(因为数组a中各元素的存储位置是连续的)。,点击打开【实例5-6】源程序。,程序运行结果如下:,返回本讲目录,6指向一维数组指针,数组指针是指向数组的指针。(1)指向一维数组的指针定义的一般格式:其中:类型标识符是说明指针所指向的一维数组中元素的类型,常量表达式说明指针指向的一维数组中元素的个数,例如,【实例5-6】中第7行语句:int(*pa)2;声明了一个指向有2个整型元素的一维数组的指针。,类型名(*指针名)常量表达式;,返回本讲目录,(2)指针赋值。一般都是用一个二维数组名赋值,例如,【实例5-6】中第10行的表达式:pa=a就是使pa指向二维数组a第0行的首地址。(3)指针移动。当使用指向一维数组的指针指向一个二维数组时,该指针移动一位,就相当于移动二维数组的一行。例如,【实例5-6】中第10行语句中的表达式:pa+则相当于pa指针在二维数组a向后移动了一行,pa指向下一行元素的首地址。,返回本讲目录,练一练,【练习5-2】输入一批学生成绩,当输入为负值时结束输入。用指针指向一个学生成绩数组,并求出这些成绩的平均值(要求用指针指向数组元素来实现)。解:(1)程序分析:设一个浮点型数组grade,数组长度为20,一个浮点型指针p,一个浮点型变量sum用于存放成绩之和,一个整型变量num用于存放输入的成绩个数,一个整型变量classes为数组实际下标值。当输入值大于0时用do-while语句循环读入每个成绩gradeclasses,然后将p指针指向该数组grade首地址,令num=classes-1得到数组最大元素下标值,使用for循环语句计算出该数组中各学生成绩的总和存入sum中,在循环体中使用指针p来表示各数组元素。最后输入sum/num的值即为输入各成绩的平均值。,返回本讲目录,返回本讲目录,点击打开【练习5-2】源程序。程序运行结果如下:,返回本讲目录,返回本讲目录,第十三讲 字符指针、指针数组、指向指针的指针和常用字符串处理函数,一、字符指针和字符串二、指针数组和指向指针的指针三、常用字符串处理函数练一练,返回本章目录,一、字符指针和字符串,【实例5-7】阅读下面的程序,分析并写出程序的运行结果。解:程序分析:第6行语句定义了一个字符型数组str,并将该数组赋初值为Hello,第7行语句定义一个字符型指针p,也为其赋初值为people,这时系统会自动为该字符串新开辟一个空间,并将指针p指向该字符串的首地址,即指向字符p。第8、9行语句为两条输出流,就是将数组str和指针p所指的字符串都输出,输出时使用字符指针的方法同字符数组的使用方法。,返回本讲目录,第10行语句p=str;的功能是将字符指针p移动到字符数组str的首地址上,此时指针p原来所指的字符串 people就丢失了。第11行语句输出指针p所指的字符串,此时输出的是数组str中字符串,所以输出Hello而不是原来的people。但需要注意的是数组str不能被重新赋值,因为数组名是数组首地址。,点击打开【实例5-7】源程序。程序运行结果如下:,1字符指针和字符串,返回本讲目录,1字符指针和字符串,1)通过指针访问字符串字符型指针用于存放字符型变量的地址,而字符串的本质是以0结尾的字符数组,一个字符型指针存储了字符数组的第一个元素的地址,也就存储了字符串的地址,这个指针就指向了字符串。例如,【实例5-7】中的第6、7行语句:char str=Hello;/定义一个字符型数组str并赋初值 char*p=“people”;/定义指针p并将其指向一个字符串 people的首地址 字符数组名与字符指针名等效,例如,【实例5-7】中的第8、9行语句:cout输出字符数组str中字符串:strendl;cout输出字符指针p所指字符串:pendl;,返回本讲目录,2)对字符指针的几点说明:(1)对于字符类型以外的数组与指针,使用cout输出的是地址,但对于字符数组与字符指针,用cout输出的是字符串。如果要输出字符数组的地址与字符指针的地址,要将它们强制转换成void型指针;(2)空指针与指向空字符串的指针是不同的,空指针指针变量的内容为NULL(0);指向空串的指针指针变量的内容不为0,但指针指向的第一个单元的内容为0。(3)字符型指针可以被重新赋值,此时原来所指的字符串会丢失。但字符数组名不能被重新赋值。,返回本讲目录,二、指针数组和指向指针的指针,【实例5-8】定义分析下面程序的运行结果,学习指针数组的使用。程序分析:本程序中首先定义了一个指向3个字符串的字符指针数组lesson和一个字符型的指向指针的指针p。首先用一个循环语句,使用指针数组名表示数组各元素将这3个字符串输出。然后再用一个循环语句,使用指向字符数组的二级指针cp指向lesson字符数组的第0个元素,然后使用该指针cp来输出这3个字符串。注意各使用指向指针的指针的使用方法。,返回本讲目录,点击打开【实例5-8】源程序。程序运行结果如下:,返回本讲目录,返回本讲目录,2指针数组,数组中的元素可以是整型、字符型,当指针变量作为数组元素时,称为指针数组,指针数组的每个元素都是同一类型的指针变量。一维指针数组定义的一般格式:其中:下标表达式为数组元素的个数,类型名为数组中每个指针元素所指向的类型,指针数组名是指针数组的名称,同时也是这个数组的首地址。,类型名*指针数组名下标表达式;,返回本讲目录,lesson是一个指针数组,它在定义的同时初始化。指针数组lesson有3个元素,每个元素都是一个字符指针,存放的是字符串的地址。其中lesson0指向字符串data structure,lesson1指向字符串java,lesson2指向字符串c language。lesson数组中的元素如图5-6所示。,指针数组的赋值与普通数组相同,但要注意所赋予的值应该是地址值,而且所赋地址的类型要与指针数组的类型相同。,图5-5 数组元素与元素地址关系图,返回本讲目录,3指向指针的指针,如果已经定义了一个指针类型,我们再定义一个指针,用于指向已经定义的指针变量,后面定义的指针变量就是一个指向指针的指针变量,简称指向指针的指针,这样的指针也称二重(级)指针。二级指针的定义格式如下:例如,【实例5-8】中的第8行语句:char*cp;就定义了一个字符型的指向指针的指针。,类型名*指针名;,返回本讲目录,三、常用字符串处理函数,【实例5-9】设有三个字符数组str、str1和str2,先给str1和str2赋初值,输出这三个字符串,然后将字符串常量“abc”复制到str中并输出其值;再将str2连接到str1后面,输出str1的值;求出这三个字符串的长度并输出;比较str和str2是否相等。注意程序中的字符串处理函数的使用方法。程序分析:初始时没有为字符数组str赋初值,这时输出str的值为不确定的值,而str1和str2的初值分别设为Ill see you和 in the morning.。使用字符串复制函数strcpy()可以将一个字符常量或一个字符串复制到另一个字符数组中。,返回本讲目录,使用字符串连接函数strcat()可将后一个字符串连接到前一个字符串并存到前面字符数组中,使用字符串长度函数strlen()可求得一个字符串的长度,使用字符串比较函数strcmp()可以判断两个字符串是否相等。点击打开【实例5-9】源程序。程序运行结果如下:,返回本讲目录,4常用的字符串处理函数,C+提供了一系列字符串操作的函数,这些函数都包含在头文件cstring中。其中经常会用到的字符串函数包括:strcpy(字符串复制,将一个字符串复制到另一个字符串变量中)、strcat(字符串连接,在字符串末端添加字符串)、strcmp(字符串比较,用来比较字符串)、strlen(字符串长度,用来求出字符串长度)。表5-1中列出了这些函数。,返回本讲目录,表5-1 常用字符串处理函数及功能说明,返回本讲目录,(1)字符串复制函数strcpy()其格式如下:功能:将s2所指向的字符串复制到s1所指向的字符数组中,然后返回s1的地址值。例如,【实例5-9】的第14行语句中strcpy(str,abc)就是将字符串abc复制到字符数组str里面。,char*strcpy(char*s1,const char*s2),返回本讲目录,(2)字符串连接函数strcat()其格式如下:功能:字符串连接函数,将字符串s2连接到字符串s1的后面,并返回s1的地址值。在【实例5-9】中第15行的语句中,strcat(str1,str2)就是将str2中的字符串 in the morning.连接到字符数组str1后面(其值为Ill see you),结果str1中的值为Ill see you in the morning.。,char*strcat(char*s1,char*s2),返回本讲目录,(3)字符串比较函数strcmp()其格式如下:功能:字符串比较函数,比较两个字符串s1和s2的大小(如果有参数n,比较前n个字符的大小)。当字符串s1大于、等于或小于字符串s2时,函数返回值分别是正数、零和负数。例如,【实例5-9】中的第19行语句:i=strcmp(str,str2);/比较两个字符串是否相等就是返回一个整数,用来判断两字符是否相等。,int strcmp(const char*s1,const char*s2,int n),返回本讲目录,(4)求字符串长度函数strlen()其格式如下:功能:返回字符串s的长度。例如,【实例5-9】的第16行语句中,strlen(str)表示输出字符数组str中字符的个数(空格也是一个字符)。,int strlen(const char*s),返回本讲目录,练一练,【练习5-3】阅读下面程序,分析运行结果。程序分析:int x=1,2,3,4,5,6,7,8,9,10;定义整型数组x,因为数组名为数组x的首地址,所以数组x中的元素地址可以分别用x、x+1x+9来表示,语句int*px5;定义一个指针数组px,每个元素都是指针,通过for语句为数组px中的元素赋值。指针数组元素与其所指向数据的关系如图5-7所示。,图5-7【练习5-3】指针数组元素与其所指向数据之间的关系,返回本讲目录,在输出流中,其中*(*(px+2)+1)表示的是数组x中的元素x5,所以输出结果为6;同理*px+1表示的是数组x中的元素x0加上1,所以输出结果为1+1=2;而*(px3)表示的数组元素为x6,所以输出结果为7;而*(px4+1)表示的是数组元素x9,所以输出结果为10。点击打开【练习5-3】源程序。程序运行结果如下:,返回本讲目录,第十四讲 指针和函数,一、指针作为函数参数二、返回指针的函数三、指向函数的指针练一练,返回本章目录,一、指针作为函数参数,【实例5-10】阅读下面程序,分析并写出程序的运行结果。程序分析:主程序中定义了两个整型变量a、b,初值分别为5、10,调用func1()时,将变量a的地址传递给指针变量p1,变量b的地址传递给指针变量p2,在func1()函数中通过指针变量p1、p2改变它们所指向的值,由于变量a、b的地址即为指针变量p1、p2所存的内存地址,所以变量a的值被改为1,b的值被改为2。指针作为函数参数时,形参变量为指针型变量(如func1的*p1和*p2),而主函数中的函数调用语句中,括号内的实参应该为变量的地址(如主函数中的&a和&b)或指针变量。,返回本讲目录,点击打开【实例5-10】源程序。程序运行结果如下:,返回本讲目录,1指针作为函数的参数,当需要在不同的函数之间传递大量数据时,程序执行时调用函数的开销就会比较大,这时,如果需要传递的数据是存放在连续的内存区域中,就可以只传递数据的起始地址,而不必传递数据的值,这样就会减小开销,提高效率。函数的参数不仅可以是基本类型的变量、对象名或函数名,而且可以是指针。指针作为函数参数是一种地址传递方式,指针可以作为函数的形参,也可以作为函数的实参。,返回本讲目录,如果以指针作为函数的形参,在调用时实参将值传递给形参,也就是使实参和形参指针变量指向同一内存地址,这样在子函数运行过程中,通过形参指针对数据值的改变也同样影响着实参所指向的数据值,从而实现参数双向传递的目的。即通过在被调用函数中直接处理主调函数中的数据而将函数的处理结果返回其调用者。例如,在【实例5-10】中第11行语句为子函数func1的调用语句:func1(括号内的&a和&b就是将变量a、b的地址作为函数参数传递给子函数func1的形参指针变量p1和p2,这时指针p1指向了变量a,指针p2指向了变量b。然后在子函数func1中使用*p1来表示变量a,用*p2来表示变量b,实现修改主函数中变量a和b两个值的功能。,返回本讲目录,二、返回指针的函数,【实例5-11】阅读下面的程序,注意观察程序的运行结果。程序分析:首先分析这个函数要实现的功能,就是在一个字符串中查找指定的字符第一次出现的位置。函数定义应包括函数的返回类型、函数名、形参表和函数体。子函数myStrCh的返回值应该是一个地址值,对应的是找到的字符第一次出现的地址,也就是指向这个位置的指针。在main()函数中调用函数myStrCh,函数的实际参数是待查找的字符串和用于查找的指定字符,并通过语句输出函数的返回结果,即指针值。注意输出指针p所指的地址时要将其强制转换为void类型的指针才能正确输出其地址。,返回本讲目录,点击打开【实例5-11】源程序。程序运行结果如下:,返回本讲目录,2返回指针的函数,函数在调用之后会有返回值,当然函数的返回值也可以为指针类型的变量。当一个函数的返回值是指针类型时,这个函数就是指针函数。指针型函数定义的一般格式:说明:数据类型表明函数返回值的类型为指针;函数名和星号“*”标识了一个指针型的函数;参数表中是函数的形参列表。,类型*函数名(参数表)函数体,返回本讲目录,【实例5-12】阅读下面程序,注意观察程序的运行结果。程序分析:本程序中,int(*pfun)(int,int)语句说明了一个函数指针pfun,该函数指针指向这样的函数:其返回类型为int,且指针指向的函数有两个整型形参,另外,还定义了个普通函数。在main()中,通过pfun指向不同的函数从而间接调用这些函数,与直接使用函数名来调用这些函数具有相同的效果。点击打开【实例5-12】源程序。程序运行结果如下:,三、指向函数的指针,返回本讲目录,3指向函数的指针,函数指针就是指向某个函数的指针,它是专门用于存放该函数代码首地址的指针变量。一旦定义了某个函数指针,它就与函数名有同样的作用,在程序中就可以像使用函数名一样,通过指向该函数的指针来调用该函数。1)函数指针定义的一般格式:说明:数据类型为函数指针所指函数的返回值类型;形参表则列出了该指针所指函数的形参类型和个数。函数指针名与星号“*”外面的圆括号“()”是必需的,表示该指针变量为指向函数的指针。,数据类型(*函数指针名)(形参表);,返回本讲目录,2)函数指针在使用之前要进行赋值,使指针指向一个已经存在函数的起始地址。其赋值语句格式为:例如,【实例5-12】中的第12行语句:pfun=add;/函数指针指向add函数3)函数调用:(1)通过函数名直接调用函数。格式如下:(2)通过函数指针间接调用函数。格式如下:,函数指针名函数名;,函数名(实参表);,(*函数指针名)(实参表);,返回本讲目录,练一练,【练习5-4】阅读下面的程序,注意观察程序的运行结果。解:程序分析如下:本程序中,fun()是一个指针型函数,其中的int*h=new int4;语句定义了一个无名数组(其长度为4),由h指向它的第一个元素,该函数返回h值。再通过main()输出所有元素,直到元素值为0时结束。点击打开【练习5-4】源程序。程序运行结果如下:,返回本讲目录,第十五讲 动态存储分配、void指针和引用,一、动态存储分配和void指针二、引用练一练,返回本章目录,一、动态存储分配和void指针,【实例5-13】阅读下面的程序,注意观察程序的运行结果。程序分析:本程序定义了两个整型指针p和q,其中指针q在定义时动态申请一个整型空间并赋初值为100,然后输出指针q所指变量的值。指针p指向动态分配的10个整型变量空间首地址,当分配空间失败时给出提示信息。否则当分配空间成功时,通过一个循环语句为指针p所指向的数组赋初值并输出,其中&pi为输出数组各元素的地址值。最后使用delete语句释放由p所指向的数组空间和q所指的变量空间。,返回本讲目录,点击打开【实例5-13】源程序。程序运行结果如下:,返回本讲目录,类型相同的大量数据,我们可以采用数组来存储,但是很多情况下,程序运行之前我们不能确定数组中有多少个元素,只能按预先估计的最大可能数量进行定义,这有可能造成内存的巨大浪费,而且一旦超过预先定义的最大长度,数组还会越界,造成程序异常甚至系统崩溃。C+中,动态内存分配技术可以使程序在运行过程中根据实际需要申请适量的内存,使用结束后还可以释放。,返回本讲目录,1new运算,new运算的作用是按指定类型和大小动态地分配内存。其定义形式如下:其中:数据类型可以是基本数据类型,也可以是用户自定义的复杂数据类型;new运算符在(堆)内存中创建一个由类型名指定类型的对象,如果创建成功,返回对象的地址;否则返回空指针NULL;初值列表给出被创建对象的初始值;由于返回的是地址,所以要用事先定义一个类型相同的指针变量来存储这个地址。,指针变量=new 类型名(初值列表);,返回本讲目录,使用new运算也可以创建同类型的多个对象数组。由于数组大小可以动态给定,随创建的对象称为动态数组。其语法格式如下:其中:下标表达式与数组初始化时的常量表达式不同,可以是变量表达式;用new申请失败时,返回NULL。申请一个动态数组,往往需要较大的空间,因此,在程序中需要对new的返回值进行判断,看是否申请成功。,指针变量=new 类型名下标表达式;,返回本讲目录,2delete运算,当程序不再需要由new分配的内存空间时,可以用delete释放这些空间,其语法格式如下:若删除的是动态数组,其语法格式如下:其中:方括号表示用delete释放为多个对象分配的地址,中不需要说明对象的个数;不管建立的动态数组是多少维,释放的格式都一样。,返回本讲目录,delete 指针变量名;,delete 指针变量名;,说明:(1)用new运算符申请分配的内存空间,必须用delete释放;(2)delete能释放的指针必须是由new分配内存空间的首地址;(3)对于一个已分配内存的指针,可以用delete释放一次;(4)new和delete运算实现了堆空间的动态分配,它在带来方便的同时也具有隐患:使用new进行内存分配后,若忘记了使用delete运算进行内存回收,就产生“内存泄露”,如果程序长时间运行,则有可能因内存耗尽而使系统崩溃,所以对new和delete要养成配对使用的良好习惯。,返回本讲目录,3void指针,在C+中,允许使用void类型的空类型指针,其定义格式如下:(1)void指针表示指针变量不指向任何一个确定类型的数据,仅仅用来存放一个地址。(2)指针变量的初始化。在定义指针变量的同时,可以给指针一个初值。例如:int a,*p=指针变量p被初始化为指向变量a(&a表示变量a的地址,&为取地址运算符),变量a的定义要出现在p之前。,void*指针变量名;,返回本讲目录,二、引用,【实例5-14】定义一个函数,实现交换两个整数的功能。要求使用引用参数,实现两个数据的交换。程序分析:通过对x、y引用a、b,在函数体中,交换变量a和b的值就是交换变量x和y的值。,返回本讲目录,图5-8【实例5-14】程序执行时变量的变化情况,返回本讲目录,点击打开【实例5-14】源程序。程序运行结果如下:,返回本讲目录,4引用的声明和操作,引用是已存在变量的别名,对引用型变量的操作实际上就是对被引用变量的操作。但定义一个引用型变量时,需要用已存在的变量对其初始化。其定义格式如下:其中:数据类型应与被引用变量的类型相同;&是引用运算符,在这里是二元操作符;变量名为已定义的变量。,数据类型,返回本讲目录,例如:int x;int 其中,a是一个引用型变量,它被初始化为对整型变量x的引用。即给整型变量x起了一个别名a,a就称为对x的引用,x称为a的引用对象。(1)声明一个引用时,必须同时对它进行初始化,使它指向一个已存在的对象;(2)一旦一

    注意事项

    本文(第五章构造数据类型.ppt)为本站会员(sccc)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开