C++程序设计-教学幻灯片

上传人:公**** 文档编号:567706385 上传时间:2024-07-22 格式:PPT 页数:504 大小:3.81MB
返回 下载 相关 举报
C++程序设计-教学幻灯片_第1页
第1页 / 共504页
C++程序设计-教学幻灯片_第2页
第2页 / 共504页
C++程序设计-教学幻灯片_第3页
第3页 / 共504页
C++程序设计-教学幻灯片_第4页
第4页 / 共504页
C++程序设计-教学幻灯片_第5页
第5页 / 共504页
点击查看更多>>
资源描述

《C++程序设计-教学幻灯片》由会员分享,可在线阅读,更多相关《C++程序设计-教学幻灯片(504页珍藏版)》请在金锄头文库上搜索。

1、2021/6/41关于关于C+C+语言课程语言课程C与与C+(C加加,加加,see-plus-plus)贝尔实验室于二十世纪八十年代在贝尔实验室于二十世纪八十年代在C C语言的基础上开发的。语言的基础上开发的。C+C+是是C C语言的超集,包含了语言的超集,包含了C C语言的所有内容,同时增加了语言的所有内容,同时增加了面向对象编程方面的内容。面向对象编程方面的内容。C+与与Java和和C#C+C+是是JavaJava和和C#C#的始祖。的始祖。JavaJava和和C#C#是是C+C+的子集与简化的子集与简化因此,学习因此,学习C+C+后学习后学习JavaJava与与C#C#会事半工倍、倍感轻

2、松。会事半工倍、倍感轻松。 2021/6/43参考书目与课时安排参考书目与课时安排参考书目参考书目C+程序设计导学程序设计导学. 李春葆著李春葆著. 北京北京: 清华大学出版社清华大学出版社C+语言程序设计教程语言程序设计教程 杨进才杨进才 沈显君沈显君 刘蓉刘蓉编著编著 清华清华大学出版社大学出版社C+ Primer (3RD)中文版中文版. Stanley B.Lippman, Josee Lajoie 著著.潘爱民潘爱民, 张丽译张丽译. 北京:中国电力出版社北京:中国电力出版社2021/6/44如何学好如何学好C+C+能细能粗能细能粗在面向过程编程部分,对数据类型、运算符、语句等要注重

3、细在面向过程编程部分,对数据类型、运算符、语句等要注重细节。做到细致掌握。节。做到细致掌握。在面向对象部分重在对概念的掌握,对每个概念回答是什么?在面向对象部分重在对概念的掌握,对每个概念回答是什么?为什么?如何?这三个问题。做到掌握思想。为什么?如何?这三个问题。做到掌握思想。重视实践重视实践和学好所有编程语言一样,做到和学好所有编程语言一样,做到“上机、上机、再上机上机、上机、再上机”。利用资源利用资源利用网络资源进行学习、交流、答疑。如清华大学的利用网络资源进行学习、交流、答疑。如清华大学的BBS站的站的C+学习园地上有大量的帖子。学习园地上有大量的帖子。 地址:地址:2021/6/45

4、第第1 1章章 C+ C+编程简介编程简介2021/6/42021/6/4本章内容本章内容1.1 1.1 计算机程序设计语言计算机程序设计语言1.2 1.2 面向过程的程序设计面向过程的程序设计1.3 1.3 面向对象的程序设计面向对象的程序设计1.4 C+1.4 C+概述概述1.5 C+1.5 C+程序实例程序实例2021/6/42021/6/41.1 1.1 计算机程序设计语言计算机程序设计语言CPU指令系统,由0、1序列构成的指令码组成如:10000000加10010000减用助记符号描述的指令系统如ADDAX,BX面向机器的语言程序设计依赖解决问题的过程客观事物描述成具有属性和行为的对

5、象对象; ; 同一类对象的共同属性和行为形成类类; ; 封装对象间通过发送和接受消息消息发生联系; 类的继承继承与多态性多态性可以提供使用现成类的机制,从而实现代码的重用.程序设计关键是定义类,并由类实例化成对象接近人的自然语言习惯,如:100+200 2021/6/42021/6/41.2 面向过程的程序设计面向过程的程序设计本质:本质:通过程序来进行数据处理通过程序来进行数据处理高级语言高级语言:1、面向过程的语言、面向过程的语言BASIC、PASCAL、C 2、面向对象的语言、面向对象的语言C+、JAVA 2021/6/42021/6/41.2 面向过程的程序设计面向过程的程序设计例如:

6、要向屏幕打印一个例如:要向屏幕打印一个“A”字符字符1、BASIC语言:PRINT “A”2、PASCAL语言:writeln(A);3、C语言:printf(“A”);4、C+语言:cout “A”;5、JAVA语言:System.out.print(A );2021/6/42021/6/4主要思想主要思想自顶向下自顶向下逐步求精逐步求精核心核心算法算法:为解决某一应用问题而采用的为解决某一应用问题而采用的解题步解题步骤。骤。一个计算机程序可以看成是由一系列任务组成一个计算机程序可以看成是由一系列任务组成的,任何一项任务如果过于复杂就将其分解成的,任何一项任务如果过于复杂就将其分解成一系列较

7、小的子任务,直至每一项任务都很小,一系列较小的子任务,直至每一项任务都很小,很容易解决。很容易解决。1.2 面向过程的程序设计面向过程的程序设计2021/6/42021/6/4基本结构基本结构1.2 面向过程的程序设计面向过程的程序设计2021/6/42021/6/4“面向过程的程序设计面向过程的程序设计”不足:不足:1 1、生产率低下,软件代码重用程度低;、生产率低下,软件代码重用程度低;2 2、软件维护困难。、软件维护困难。“面向对象的程序设计面向对象的程序设计”本质:本质:把数据和处理数据的过程当成一个整体即把数据和处理数据的过程当成一个整体即对象。对象。“面向对象的程序设计面向对象的程

8、序设计”优点:优点:与人类习惯的思维方式一致。与人类习惯的思维方式一致。可重用性好。可重用性好。可维护性好。可维护性好。1.3 面向对象的程序设计面向对象的程序设计2021/6/42021/6/4对象对象是实现世界中是实现世界中的一个实际存在的一个实际存在的事物的事物张三李四抽象类类是具有相同是具有相同属性和服务属性和服务的一组对象的一组对象的概括的概括属性属性服务服务性别,年龄说话,行走具体化继承新类新类人说话,行走性别,年龄大学生性别,年龄,专业说话,行走,学习消息消息1.3 面向对象的程序设计面向对象的程序设计2021/6/42021/6/4封装:封装:信息隐蔽:通过将类定义的成员设置成

9、不同的访问权限来实现。继承和派生:继承和派生:在程序中定义类,当出现两个或多个类享有相似的情在程序中定义类,当出现两个或多个类享有相似的情况,就不必重复在类中定义,可通过继承,从其他类况,就不必重复在类中定义,可通过继承,从其他类派生出其他类。派生出其他类。多态性:多态性:指在一般类中定义的属性和行为,被特殊类继承之后,指在一般类中定义的属性和行为,被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为。可以具有不同的数据类型或表现出不同的行为。1.3 面向对象的程序设计面向对象的程序设计2021/6/42021/6/41.4 C+1.4 C+语言概述语言概述全面支持全面支持C C+语言的

10、产生语言的产生 1983加入类CC+ANSIC+1994标准化C+语言的特点语言的特点 面向对象面向对象 比比C更完善、安全、高效更完善、安全、高效2021/6/42021/6/41.3 C+1.3 C+程序开发过程程序开发过程程序代码的录入、修改执行预处理指令,词法分析、语法分析后生成目标程序与其它目标程序或库连接,生成可执行程序2021/6/42021/6/41.4 C+1.4 C+程序实例程序实例 /*/*程序文件名程序文件名:p1_1.cpp*:p1_1.cpp*本程序显示本程序显示:HelloC+!*:HelloC+!*设计者设计者: :鲁莹鲁莹时时 间间:8-27-2007*:8-

11、27-2007*/*/#include/#include/载入头文件载入头文件usingnamespacestd;/usingnamespacestd;/使用命名空间使用命名空间stdstdvoid main( ) void main( ) /程序入口程序入口 coutHelloC+!endl;coutHelloC+!endl; 预处理命令预处理命令无返回值无返回值无参数、无返回值的主函数无参数、无返回值的主函数主函数名主函数名函数开始函数开始函数体函数体语句结束标志语句结束标志函数结束函数结束 运行结果运行结果运行结果运行结果:Hello C+!Hello C+!注释块注释块注释行注释行 在

12、在C+C+程序中,注释块由程序中,注释块由“/*”“/*”开始,由开始,由“*/”“*/”结束,可以实现多行注释结束,可以实现多行注释 。 也可使用也可使用“/”“/”进行单行注释。进行单行注释。 C+ C+语言的预处理命令都是以语言的预处理命令都是以“#”“#”号开头。号开头。iostream是一个头文件是一个头文件, ,系统系统头文件不带头文件不带.h.h后缀后缀 cout cout为标准输出流对象,它与显示器相连。为标准输出流对象,它与显示器相连。 是插入操作是插入操作符,符,endlendl为换行符号。整个语句的功能是将为换行符号。整个语句的功能是将”Hello C+ ”Hello C

13、+ !”!”字符串与字符串与endlendl依次插入到依次插入到coutcout中中 main main是主函数名,一个是主函数名,一个C+C+语言程序有且仅有语言程序有且仅有一个一个mainmain函数。函数。C+C+程序执行时就是从程序执行时就是从mainmain函函数开始数开始. . C+ C+语言规定:语句以分号结束语言规定:语句以分号结束2021/6/42021/6/4?为什么为什么: : 标准标准C+C+库提供的对象等都放在标准名字空间库提供的对象等都放在标准名字空间stdstd中中, ,要使用它们要使用它们, , 必须要声明使用标准名字空间必须要声明使用标准名字空间std.std

14、. 使用标准名字空间使用标准名字空间stdstd有有3 3种方式种方式: :整体声明整体声明 using namespace std; using namespace std; 使用时单个对象临时声明使用时单个对象临时声明 std:coutstd:coutHello Hello C+C+std:endlstd:endl; ;单个对象使用前声明单个对象使用前声明 using using std:coutstd:cout; ; 整体声明整体声明#include using namespace std; void main( ) cout Hello C+!endl; 单个对象临时声明单个对象临时声

15、明# include void main ( ) std:cout”Hello C+!”std:endl; 单个对象使用前声明单个对象使用前声明# include using std:cout;using std:endl;void main ( ) cout”Hello C+!” cin 对象对象1 1 对象对象2.2.对象对象n n;cout 对象对象1 对象对象2.连用,使用格式为:连用,使用格式为:意思是从标准输入流对象键盘上提取意思是从标准输入流对象键盘上提取n n个数据分别给对象个数据分别给对象1 1、对象、对象2 2、.、对象、对象n n。C+C+中使用对象中使用对象cout c

16、out 作为标准输出流对象,通常代表显示设备,作为标准输出流对象,通常代表显示设备,cout cout 与插与插入操作符入操作符连用,使用格式为:连用,使用格式为:意思是依次从将对象意思是依次从将对象1 1、对象、对象2 2、.、对象、对象n n插入到标准输出流对象中,从而插入到标准输出流对象中,从而实现了对象在显示器上的输出实现了对象在显示器上的输出 . .C C+ + 输入输入/ /输出简介输出简介2021/6/42021/6/4本章小结本章小结p程序设计语言经历了从机器语言、汇编语言、高级语言、面向程序设计语言经历了从机器语言、汇编语言、高级语言、面向对象的语言的发展过程对象的语言的发展

17、过程, , 使得编程语言与人的自然语言越来越使得编程语言与人的自然语言越来越接近,编程效率越来越高。接近,编程效率越来越高。p程序设计方法经历了面向过程的方法、结构化的方法、面向对程序设计方法经历了面向过程的方法、结构化的方法、面向对象的方法的发展过程。象的方法的发展过程。pC+C+语言具有全面兼容语言具有全面兼容C C与面向对象的特点,支持结构化与面向与面向对象的特点,支持结构化与面向对象程序设计方法。对象程序设计方法。p面向对象的基本概念有:对象、类、封装、继承、消息、多态面向对象的基本概念有:对象、类、封装、继承、消息、多态性。性。pC+C+程序设计的步骤有编辑、预编译、编译、连接、调试

18、与运程序设计的步骤有编辑、预编译、编译、连接、调试与运行。行。p程序注释有两种方法,应培养给程序写注释的好习惯。程序注释有两种方法,应培养给程序写注释的好习惯。p预处理指令预处理指令includeinclude在编译的预处理阶段将头文件搬到程序中,在编译的预处理阶段将头文件搬到程序中,包含文件是包含文件是C+C+程序的必不可少的部分。程序的必不可少的部分。p标准标准C+C+的类库定义在名字空间的类库定义在名字空间stdstd中,可以通过三种方法使用中,可以通过三种方法使用名字空间。名字空间。2021/6/42021/6/4实验一实验一熟悉熟悉Vc+上机环境上机环境编程编程实现在屏幕上显示输出实

19、现在屏幕上显示输出“Hello,VC+!”实现在屏幕上显示输出以下图形:实现在屏幕上显示输出以下图形: * * * * * * * * * * * * * * * * *2021/6/42021/6/4第第2 2章章 C+ C+数据类型数据类型主讲:鲁莹主讲:鲁莹主讲:鲁莹主讲:鲁莹2021/6/423本章内容本章内容 2.12.1 数据类型数据类型概述概述 2.22.2 常量与变量常量与变量 2.32.3 基本类型基本类型 2.42.4 运算符和表达式运算符和表达式 2.52.5 类型转换类型转换2021/6/4基本整型基本整型 (intint) 短整型短整型 (shortshort) 整型

20、整型 长整型长整型 (longlong) 无符号型无符号型 (unsignedunsigned) 基本类型基本类型 单精度型单精度型 (floatfloat) 实型实型(浮点型浮点型) 双精度型双精度型 (doubledouble) 字符型字符型 (charchar) 扩展双精度型扩展双精度型 (long doublelong double)数据类型数据类型 布尔型布尔型 (boolbool) 空类型空类型 (voidvoid) 数组类型数组类型 ( ) 指针类型指针类型 (*) 构造类型构造类型 结构体类型结构体类型 ( (structstruct) 共用体类型共用体类型 (unionuni

21、on) 枚举型枚举型 (enumenum) 类类 (classclass)2.1 数据类型概述数据类型概述C+中新增2021/6/42.1 2.1 数据类型概述数据类型概述数据类型和内存空间数据类型和内存空间不同的数据类型,加上不同的修饰符就具有了不不同的数据类型,加上不同的修饰符就具有了不同的特点,在内存中占用的空间也不同,因而其同的特点,在内存中占用的空间也不同,因而其所能表示的数值范围也不尽相同。所能表示的数值范围也不尽相同。内存单元的单位是字节,因此用来表示数据类型内存单元的单位是字节,因此用来表示数据类型的长度的单位也是字节。的长度的单位也是字节。2021/6/42.1 2.1 数据

22、类型概述数据类型概述注意整型注意整型int的长度等于机器的字长:的长度等于机器的字长:16位机:位机:int=2字节;字节;32位机:位机:int=4字节。字节。但是但是shortshort和和longlong表示的数据长度是固定的,任表示的数据长度是固定的,任何支持标准何支持标准C+C+的编译器都是如此,因而如果需的编译器都是如此,因而如果需要编写可移植性好的程序,应将整型声明为要编写可移植性好的程序,应将整型声明为shortshort或或longlong。2021/6/42.1 2.1 数据类型概述数据类型概述例题例题编写一个程序,输出基本数据类型编写一个程序,输出基本数据类型char,

23、int, float, double,bool的长度。的长度。提示:提示:使用使用sizeof(数据类型数据类型) 能够获取不同数据类型能够获取不同数据类型的长度。的长度。2021/6/42.1 2.1 数据类型概述数据类型概述/输出基本数据类型的长度输出基本数据类型的长度#include using namespace std;void main()cout“char :”sizeof(char)“字节n;coutint:sizeof(int)字节n;coutfloat :sizeof(float)字节n;coutdouble:sizeof(double)字节n;coutbool:sizeo

24、f(bool)字节n;2021/6/42.2 2.2 常量与变量常量与变量2.2.1 常量2.2.2 变量2021/6/4#include using namespace std;void main(void) const int PRICE=30; int num,total; float v ,r,h; num=10; total=num*PRICE; couttotal endl; r=2.5; h=3.2; v=3.14159*r*r*h; coutv endl;常量变量变量先声明后使用Page31字符常量2021/6/42.2.1 2.2.1 常量常量v严格来说,常量又分成符号常量和

25、常数严格来说,常量又分成符号常量和常数。v符号常量符号常量:v代表一个固定不变值的名字代表一个固定不变值的名字v常数常数(整型和浮点型)整型和浮点型):v程序中使用的具体的数据程序中使用的具体的数据2021/6/42.2.1 2.2.1 常量与常量与符号常量符号常量符号常量符号常量C+中提供了一个关键字中提供了一个关键字const,用来区分常量和,用来区分常量和变量。并且由于常量代表一个固定的值,并且该值变量。并且由于常量代表一个固定的值,并且该值在程序运行过程中不能够被改变,所以要求常量在在程序运行过程中不能够被改变,所以要求常量在定义的时候必须进行初始化。定义的时候必须进行初始化。 定义形

26、式有:定义形式有: const 数据类型数据类型 符号常量名符号常量名= =初始值初始值; 例如:例如:const double PI=3.1415926;2021/6/4M注意: constdouble PI; PI=3.1415926; /error constdouble PI= ; /error constint M=max(15,23); /error #define 符号常量名 初始值 例如:#definePI3.14159262.2.1 2.2.1 常量与常量与符号常量符号常量2021/6/42.2.2 2.2.2 变变 量量什么是变量?什么是变量?在在C+C+中,变量是存储信息

27、的地方。变量中,变量是存储信息的地方。变量的实质是内存中的一个地址空间,在这个的实质是内存中的一个地址空间,在这个地址空间中可以进行数据的存储和读取。地址空间中可以进行数据的存储和读取。2021/6/42.2.2 2.2.2 变变 量量变量有三个基本要素变量有三个基本要素:名字、类型和值名字、类型和值。C+的程序设计中,在使用变量前必须首先的程序设计中,在使用变量前必须首先定义定义变量变量,即指定变量的,即指定变量的名称名称与与数据类型数据类型。变量一经定义,系统根据其数据类型在内存中为变量一经定义,系统根据其数据类型在内存中为该变量分配一定的存储单元,在该存储单元中可该变量分配一定的存储单元

28、,在该存储单元中可存放变量的存放变量的值值。2021/6/4变量的定义变量的定义 一般格式为一般格式为: :数据类型关键字数据类型关键字 变量名表变量名表; ; 说明说明:(:(1)1)变量名表变量名表:可以包含若干个变量,彼此间用:可以包含若干个变量,彼此间用 逗号逗号分开。分开。变量名必须是合法的标识符,变量名必须是合法的标识符,不不 能用能用C+C+的关键字作为变量名。的关键字作为变量名。 (2) (2)数据类型数据类型:变量可以被定义为基本数据类型:变量可以被定义为基本数据类型 和构造类型。和构造类型。 例如:例如: int x ; float area,width,length ;

29、2021/6/4变量的定义变量的定义 注意: 与C语言不同,C+语言中的变量定义不必位于程序的开始,可以穿插在其它语句中间。变量最好在使用时才定义,这样可以增加程序的可读性,避免变量发生混淆。2021/6/4初始化变量初始化变量 在定义变量的同时给其一个初始值,称为初始化变量。例如: unsignedshort width=5; longwidth=8,length=8; double area,radius=20;或或unsigned shortwidth(5);long width(8),length(8);“函数表示法函数表示法”doublearea,radius(20);2021/6/

30、4初始化变量初始化变量#include using namespace std;void main()Int myAge= 18;cout“myAge=” myAgeendl;myAge= 20;cout“myAge=” myAgeendl;运行结运行结果:果:myAge=18myAge=202021/6/41.整型2.实型(浮点型)3.字符型4.布尔类型5.void类型小结2.3 2.3 基本类型基本类型void main( )2021/6/4整整 型型 1. 整型常量的表示 2. 整型变量的分类关键字:关键字:int2021/6/4整型常量的表示整型常量的表示(1)十进制整数:十进制整数:

31、十进制整数:十进制整数:非非0开头的,以开头的,以0至至9数字、正负号组成数字、正负号组成的常数,如的常数,如1234,-10为合法十进制整常数,而为合法十进制整常数,而123.0,1.23E+2是非法的十进制整常数。是非法的十进制整常数。(2)八进制整数:八进制整数:八进制整数:八进制整数:以以O开头的,由开头的,由0至至7数字组成的数字串,数字组成的数字串,不能带符号,如不能带符号,如O1234,O10为合法八进制整常数,为合法八进制整常数,而而1234,028则则是非法的八进制整常数。是非法的八进制整常数。2021/6/4整型常量的表示整型常量的表示(3)(3)十六进制整数十六进制整数十

32、六进制整数十六进制整数: : : :以以0x(0x(或或0X)0X)开头的开头的, ,由由0 0至至9 9数字和数字和a a至至f(f(或或A A至至F)F)字符组成字符组成, ,不能带符号,如不能带符号,如0x100x10,0x2f0x2f,0xa0xa为合法的十六进制整常数,而为合法的十六进制整常数,而1212,0xgf0xgf,20H20H是非是非法的十六进制整常数。法的十六进制整常数。注意:注意:C+C+中,十进制数有正负之分,但八进制和十六中,十进制数有正负之分,但八进制和十六进制数只能表示无符号整数。进制数只能表示无符号整数。 v以下选项中可以作为以下选项中可以作为C/C+C/C+

33、语言合法整数的是语言合法整数的是 。 A) 10110B B) 0368 C) 0Xffa D) x2a22021/6/4整型变量的分类整型变量的分类(1) signed:表示有符号位:表示有符号位(可缺省,可缺省,int型型); (2) unsighed:表示无符号位:表示无符号位 (unsigned int型型);(3) long:表示长型:表示长型( long int 型和型和unsigned long 型型);(4) short:表示短型:表示短型( short int 型和型和unsigned short 型型) ;例如例如: signed int a; 等价于等价于 int a;

34、unsigned int a; 等价于等价于 unsigned a; long int a; 等价于等价于 long a; short int a; 等价于等价于 short a;2021/6/4整型变量的分类整型变量的分类 在十进制、八进制和十六进制表示的整常数中,若在十进制、八进制和十六进制表示的整常数中,若数字串的后面加上字母数字串的后面加上字母l(l(或或L)L),则说明该常数为长整,则说明该常数为长整数,如数,如12L12L,027l027l,0xa1L0xa1L,0x9FL0x9FL。若数字串的后面加。若数字串的后面加上字母上字母u(u(或或U)U),则说明该常数为无符号整数,如,

35、则说明该常数为无符号整数,如5U5U。说明说明:2021/6/4实实 型型 1. 实型常量表示法 2. 实型变量的分类关键字:关键字:float和和double2021/6/4(1)小数表示法:小数表示法:由由符号符号符号符号、数字数字数字数字和和小数点小数点小数点小数点组成的常数,可组成的常数,可以省去整数部分,只保留小数部分,但绝对不能没有小以省去整数部分,只保留小数部分,但绝对不能没有小数点。如数点。如2.55,0.0,-12.3,.234,250.等都是合法的十等都是合法的十进制小数。进制小数。(2)科学表示法:科学表示法:在小数表示法后加在小数表示法后加e e(或(或E E)及指数部

36、分。)及指数部分。注意注意注意注意:E E E E或或或或e e e e的前面的前面的前面的前面必须要有必须要有数字数字数字数字,且,且E E E E后面后面后面后面的指数必须的指数必须为为整数整数整数整数,指数部分,指数部分可正可负可正可负可正可负可正可负。如。如2.1E+5,123E-3,123e3,123.e3都是合法的,而都是合法的,而345,-.5,3.E,e5等都等都是非法的指数形式。是非法的指数形式。实型常量表示法实型常量表示法2021/6/4实型变量的分类实型变量的分类(1)单精度型:单精度型:float型型; (数据长度为数据长度为4个字节个字节)(2)双精度型:双精度型:d

37、ouble型型; (数据长度为数据长度为8个字节个字节)(3)扩展双精度型:扩展双精度型:long double型型; (数据长度为数据长度为16个字节个字节)2021/6/4实型变量的分类实型变量的分类 1. 1. 在在C+C+中,一个实型常数如果没有任何中,一个实型常数如果没有任何说明,则表示说明,则表示double型(默认型),如:型(默认型),如:12.3。 2. 2. 若要表示若要表示float型数,则必须在实型数后型数,则必须在实型数后面加上面加上F或或f,如:,如:12.3f,12.3e4f。 3. 3. 若要表示若要表示long double型数,则必须在实型数,则必须在实数后

38、加上数后加上L或或l,如:,如:12.3L,12.3e4L。 说明说明: :2021/6/4字字 符符 型型 1. 字符型常量 2. 字符串常量关键字:关键字:关键字:关键字:char 例如:例如: char c; / / / /* * * *字符变量字符变量字符变量字符变量c c c c在内存中占在内存中占在内存中占在内存中占 用一个字节用一个字节用一个字节用一个字节*/*/*/*/2021/6/4一般字符常量:一般字符常量:用用单引号单引号单引号单引号括起来的括起来的一个字符一个字符一个字符一个字符,其值为其值为ASCII代码代码值。如值。如a, A, #, $。 在内存中,字符数据是以在

39、内存中,字符数据是以ASCII码值存储的(即以整数表示),码值存储的(即以整数表示),占据一个字节占据一个字节占据一个字节占据一个字节。因此。因此C+C+使字符数据和整型数据之间可以通用。使字符数据和整型数据之间可以通用。如:如: A=65=0101=0x41=01000001 A和a是不 a=97=0141=0x61=01100001 同的字符常量 0=48=060=0x30 0和0是截然 1=49=061=0x31 不同的两个数字符型常量字符型常量2021/6/4HELLO0字符串常量字符串常量字符串常量字符串常量字符串常量字符串常量 是用一对是用一对双引号双引号双引号双引号括起来的括起来

40、的字符序列字符序列字符序列字符序列。如。如“a”,“a”, “123”, “How do you do ?n”,“¥1.23”等等都是字符串常量。字符串中可以出现空格或其他字符,都是字符串常量。字符串中可以出现空格或其他字符,也可以包含也可以包含C+C+以外的字符,如以外的字符,如汉字汉字等。等。 v在在C+C+中,中,字符串常量字符串常量字符串常量字符串常量和和字符常量字符常量字符常量字符常量是不同的,字符串常是不同的,字符串常量中的字符连续存储,并在最后加上字符量中的字符连续存储,并在最后加上字符0000作为作为字字字字符串结束的标志符串结束的标志符串结束的标志符串结束的标志。例如字符串。

41、例如字符串“HELLO”HELLO”在内存中占连在内存中占连续续6 6个内存单元,如图:个内存单元,如图:2021/6/4字符串常量字符串常量 字符串常量和字符常量的字符串常量和字符常量的区别区别为:为: 表现形式不同:表现形式不同:“x”, x 在内存中存放时所占空间不同:在内存中存放时所占空间不同:字符常量占字符常量占1字节字节用于存用于存放字符的放字符的ASCII码值;而字符串常量除码值;而字符串常量除每个字符占用每个字符占用1字节字节存放存放其其ASCII码值外,还需码值外,还需1字节存放结束标志字节存放结束标志0。例如例如“x”在内存在内存中占连续两个单元中占连续两个单元( (即即2

42、 2个字节个字节) ),第二个单元存放,第二个单元存放0结束符,结束符,而字符常量而字符常量x占一个字节。占一个字节。 操作不同:操作不同:字符常量可以在一定范围与整数进行加减运字符常量可以在一定范围与整数进行加减运算。如算。如r-a+3是合法的,而是合法的,而“r”-“a”+3是非法的。是非法的。 存放两者的变量不同:存放两者的变量不同:字符常量存放在字符常量存放在字符变量字符变量中,而中,而字符串常量需要存放在一个一维字符串常量需要存放在一个一维字符数组字符数组中。如:中。如: char ch=a;是正确的,而是正确的,而char ch=“a”;是不正确的。是不正确的。即不能将字符即不能将

43、字符串常量赋给字符变量。串常量赋给字符变量。2021/6/4布尔类型布尔类型布布布布尔尔尔尔“bool”是是表表示示逻逻逻逻辑辑辑辑变变变变量量量量的的专专有有名名词词,所所代代表表的的意意义义就就只只有有“真真true”和和“假假false”两两种种。布布尔尔数数据据是是用用来来控控制制程程序序的的执执行行方方式式的的,或或者者说说是是用用来来处处理理程程序序中中判断或比较结果的。判断或比较结果的。例如:例如:bool flag=true; / 声明一个布尔变量声明一个布尔变量 double d=5.32; if (flag=false) d=3.24; 由由定定义义,true转转为为整整型

44、型值值时时为为1 1,false为为0 0。相相应应的的,非非零零值值可可以以隐隐式式地地转转为为true,而而0 0为为false。bool类类型型的的变量至少占据和变量至少占据和char一样的空间。一样的空间。2021/6/42.4 2.4 运算符与表达式运算符与表达式2021/6/456基本算术运算符+-*/(若整数相除,结果取整)%(取余,操作数为整数)优先级与结合性先乘除,后加减,同级自左至右+,-(自增、自减)例:i+;-j;Page57基本数据类型和表达式2021/6/457举例n=n+5表达式的类型等号左边对象的类型表达式的值等号左边对象被赋值后的值Page58基本数据类型和表

45、达式2021/6/458有10种复合运算符:+=,-=,*=,/=,%=,=,&=,=,|=例a+=3等价于a=a+3x*=y+8等价于x=x*(y+8)基本数据类型和表达式2021/6/459a=5表达式值为5a=b=c=5表达式值为5,a,b,c均为5a=5+(c=6)表达式值为11,a为11,c为6a=(b=4)+(c=6)表达式值为10,a为10,b为4,c为6a=(b=10)/(c=2)表达式值为5,a为5,b为10,c为2a+=a-=a*a相当于a=a+(a=a-a*a)Page60基本数据类型和表达式2021/6/460格式表达式1,表达式2求解顺序及结果先求解1,再求解2,最终

46、结果为表达式2的值例a=3*5,a*4最终结果为60Page61基本数据类型和表达式2021/6/461关系运算是比较简单的一种逻辑运算,优先次序为:=!=优先级相同(高) 优先级相同(低)关系表达式是一种最简单的逻辑表达式其结果类型为bool,值只能为true或false。例如:ab,cb)&(xy)其结果类型为bool,值只能为true或false基本数据类型和表达式2021/6/463一般形式表达式1?表达式2:表达式3表达式1 必须是 bool 类型执行顺序先求解表达式1,若表达式1的值为true,则求解表达式2,表达式2的值为最终结果若表达式1的值为false,则求解表达式3,表达式

47、3的值为最终结果例: x=ab? a:b;基本数据类型和表达式2021/6/464条件运算符与条件表达式注意:条件运算符优级高于赋值运算符,低于逻辑运算符表达式2、3的类型可以不同,条件表达式的最终类型为 2 和 3 中较高的类型。例: x=ab? a:b;基本数据类型和表达式2021/6/465sizeof运算符语法形式sizeof(类型名)或sizeof(表达式)结果值:“类型名”所指定的类型或“表达式”的结果类型所占的字节数。例:sizeof(short)sizeof(x)基本数据类型和表达式2021/6/466运算规则将两个运算量的每一个位进行逻辑与操作举例:计算 3 & 5 3: 0

48、 0 0 0 0 0 1 1 5:(&) 0 0 0 0 0 1 0 13 & 5: 0 0 0 0 0 0 0 1用途:将某一位置0,其它位不变。例如:将char型变量a的最低位置0:a=a&0376;取指定位。例如:有charc;inta;取出a的低字节,置于c中:c=a&0377;基本数据类型和表达式2021/6/467运算规则将两个运算量的每一个位进行逻辑或操作举例:计算 3 | 5 3: 0 0 0 0 0 0 1 1 5:(|) 0 0 0 0 0 1 0 13 | 5: 0 0 0 0 0 1 1 1用途:将某些位置1,其它位不变。例如:将int型变量a的低字节置1:a=a|0x

49、ff;基本数据类型和表达式2021/6/468运算规则两个操作数进行异或:若对应位相同,则结果该位为 0,若对应位不同,则结果该位为 1,举例:计算 071052 071: 0 0 1 1 1 0 0 1 052: () 0 0 1 0 1 0 1 0 071052 : 0 0 0 1 0 0 1 1基本数据类型和表达式2021/6/469位运算按位异或()用途:使特定位翻转(与0异或保持原值,与1异或取反) 例如:要使 01111010 低四位翻转: 0 1 1 1 1 0 1 0 () 0 0 0 0 1 1 1 10 1 1 1 0 1 0 1基本数据类型和表达式2021/6/470单目

50、运算符,对一个二进制数按位取反。例: 025:0000000000010101 025:1111111111101010基本数据类型和表达式2021/6/471左移运算()右移后,低位:舍弃高位:无符号数:补0有符号数:补“符号位”基本数据类型和表达式2021/6/472运算符优先级基本数据类型和表达式 (1) 运算符的优先级按单目、双目、三运算符的优先级按单目、双目、三目、赋值依次降低。目、赋值依次降低。(2) 算术、移位、关系、按位、算术、移位、关系、按位、逻辑运算的优先级依次降低。逻辑运算的优先级依次降低。 2021/6/473运算符优先级括号+,-,sizeof*,/,%+,-=,!=

51、位运算&|?:赋值运算逗号运算低高基本数据类型和表达式2021/6/4742.52.5 类型转换类型转换2.5.1 2.5.1 自动类型转换自动类型转换 2.5.2 2.5.2 强制类型转换强制类型转换2021/6/4752.5.1 2.5.1 自动类型转换自动类型转换基本原则:编译系统自动将低类型数据转换为高类型数据。 long double 高高 double float unsigned long long unsigned 低低 int char , short 2021/6/476 强制类型转换强制类型转换是靠强制类型转换是靠强制类型转换控制运算控制运算符符实现的,其一般形式为:实现

52、的,其一般形式为: 数据类型数据类型(操作数操作数) (第一种第一种C+C+格式)格式) 或或 (数据类型数据类型)操作数操作数 (第二种(第二种C+C+格式)格式) 其中操作数可以是其中操作数可以是变量名变量名或或表达式表达式,功能,功能是把操作数值的数据类型是把操作数值的数据类型暂时强行转换暂时强行转换为指定为指定的数据类型的数据类型。例如:例如:double(a)、int(x+y)、float(5%3)。2.5.2 2.5.2 强制类型转换强制类型转换2021/6/477M注意:注意:数据类型转换仅仅是为了数据类型转换仅仅是为了本次操作本次操作中中对操作数进行一时的转换,并不能改变对操作

53、数进行一时的转换,并不能改变原数原数据类型说明据类型说明中所规定的数据类型。中所规定的数据类型。如果使用第二种格式,当操作数为如果使用第二种格式,当操作数为表表达式达式时,表达式应用括号时,表达式应用括号括起来括起来。例如:。例如:(int)(x+y)不不能写成能写成(int)x+y 。2021/6/478实验二C+基础编程练习编程实现三个数求最大值。编程实现三个数求最大值。编程实现求解一元二次方程的解。编程实现求解一元二次方程的解。2021/6/479C+C+C+C+语言程序设计语言程序设计语言程序设计语言程序设计ProgrammingProgrammingin in C+C+ 主讲主讲主讲

54、主讲: : : :鲁莹鲁莹鲁莹鲁莹第第3 3章章 结构化程序设计结构化程序设计2021/6/480第三章第三章 结构化程序设计结构化程序设计3.1 C+语言输入输出流语言输入输出流3.2 结构化程序设计概述结构化程序设计概述3.3 顺序结构程序设计顺序结构程序设计3.4 选择结构程序设计选择结构程序设计3.5 循环结构程序设计循环结构程序设计3.6 程序设计举例程序设计举例2021/6/4813.1 C+3.1 C+语言输入输出流语言输入输出流 在在C+C+中中,将将数数据据从从一一个个对对象象到到另另一一个个对对象象的的流流动动抽抽象象为为“流流”。从从流流中中获获取取数数据据的的操操作作称

55、称为为提提取取操操作作,向向流流中中添添加加数数据据的的操操作作称称为为插插入入操操作作。数数据据的的输输入入输输出出是是通通过过输输入入输输出出I/OI/O流流来实现的。来实现的。 C+C+提提供供了了I/OI/O流流机机制制,完完成成对对输输入入输输出出的的操操作作管管理理,包包括括流流输输入入和和流流输输出出。cin和和cout是是预预定定义义的的流流对对象象。cin用用来来处处理理标标准准输输入入,即即键键盘盘输输入入;cout用用来来处处理理标标准准输输出出,即即屏屏幕幕输输出出。由由于于cin和和cout被被定定义义在在“iostream.h”头头文文件件中中,在在使使用用它它们们

56、之之前前,要要用用预预编编译译命命令令“#include”将将“iostream.h”(即即所所使用的头文件)包括到用户的源程序中。即源文件中需有:使用的头文件)包括到用户的源程序中。即源文件中需有: #include 2021/6/482F1.1.无格式输出无格式输出coutcout “”是预定义的是预定义的插入符插入符,使用,使用“”向向coutcout输出流中输出流中插入数据,便可实现在屏幕上插入数据,便可实现在屏幕上显示输出显示输出。格式如下:。格式如下: cout表达式表达式1表达式表达式2 表达式表达式n ; 或分成多行:或分成多行: cout表达式表达式1 表达式表达式2 ”是是

57、预预定定义义的的提提取取符符,使使用用“”从从cin输输入入流流中中提取数据,便可实现提取数据,便可实现键盘输入键盘输入。格式如下:。格式如下: cin 数据数据1 数据数据2 数据数据n ; 也可写成多行:也可写成多行: cin 数据数据1 1 数据数据2 2 数据数据n ;float f;long l;cinfl; 2021/6/484F按按特定的格式特定的格式进行输入输出,例如对进行输入输出,例如对 double pi=3.1415; 如如果果希希望望显显示示的的是是3.14,即即保保留留两两位位小小数数,且且域域宽宽为为5个个字字符符并换行,此时如用下面的语句则不能完成。并换行,此时如

58、用下面的语句则不能完成。 coutcoutpi“n”; “n”; /系统默认显示系统默认显示6 6位有效数字位有效数字 为为此此C+C+提提供供了了控控制制符符(manipulators),用用于于对对IO流流的的格格式式进进行行控控制制。使使用用控控制制符符,把把上上述述语语句句改改为为如如下下形形式式则则可以完成需求。可以完成需求。 coutsetw(5)setprecision(3)piendl; 控控制制符符是是在在头头文文件件iomanip.h中中预预定定义义的的对对象象,可可以以直直接接插插 入入 流流 中中 。 使使 用用 控控 制制 符符 时时 , 要要 在在 源源 文文 件件

59、 中中 添添 加加#include 预处理命令。常用控制符如预处理命令。常用控制符如表表3.1所示。所示。3.1.2 C+3.1.2 C+语言格式输入输出语言格式输入输出2021/6/485表表3.1 I/O3.1 I/O流的常用控制符流的常用控制符控控 制制 符符描描 述述 endldecocthexsetiosflags(ios:uppercase)resetiosflags(ios:uppercase)setw(n)setfill(c)setprecision(n)setiosflags(ios:fixed)setiosflags(ios:scientific)setiosflags(i

60、os:left)setiosflags(ios:right)setiosflags(ios:showpoint)setiosflags(ios:showpos) 插入换行符并刷新流插入换行符并刷新流 数值数据采用数值数据采用十十进制表示进制表示(默认默认)数值数据采用数值数据采用八八进制表示进制表示数值数据采用数值数据采用十六十六进制表示进制表示设置设置16进制数进制数大写大写输出输出取消取消16进制数进制数大写大写输出输出(默认默认)设域宽为设域宽为n个字符个字符(默认实宽默认实宽)设填充字符为设填充字符为c (默认空格默认空格)设显示小数精度为设显示小数精度为n位位(默认默认6位位)用定点

61、方式表示实数用定点方式表示实数用科学计数法表示浮点数用科学计数法表示浮点数 左左对齐对齐(默认默认)右右对齐对齐强制显示强制显示小数点小数点和和无效无效0强制显示强制显示正数符号正数符号 2021/6/486What is exact output?#include #include / for setprecision( )using namespace std;void main ( ) float myNumber = 123.4587 ; cout fixed showpoint ; / use decimal format / print decimal points cout “N

62、umber is ” setprecision(3) myNumber endl ; / set precisionOutput of program:Number is 123.4592021/6/487#include #include using namespace std;void main ( ) int myNumber = 123 ; int yourNumber = 5 ; cout setw ( 10 ) “Mine” setw ( 10 ) “Yours” endl; cout setw ( 10 ) myNumber setw ( 10 ) yourNumber endl

63、 ;What is exact output?12345678901234567890 Mine Yours 123 52021/6/488#include #include / for setprecision( )using namespace std;void main ( ) float myNumber = 123.4 ; float yourNumber = 3.14159 ; cout fixed showpoint ; / use decimal format / print decimal points cout “Numbers are: ” setprecision (

64、4 ) endl setw ( 10 ) myNumber endl setw ( 10 ) yourNumber endl ;Numbers are: 123.4000 3.1416What is exact output?2021/6/489 float x = 312.0 ; float y = 4.827 ; cout fixed showpoint ; cout setprecision ( 2 ) setw ( 10 ) x endl 3 1 2.00 setw ( 10 ) y endl ; 4.83 cout setprecision ( 1 ) setw ( 10 ) x e

65、ndl 3 1 2.0 setw ( 10 ) y endl ; 4.8 cout setprecision ( 5 ) setw ( 7 ) x endl 312.00000 setw ( 7 ) y endl ; 4.82700More Examples2021/6/4903.2 3.2 结构化程序设计概述结构化程序设计概述1. 1. 结构化程序的基本结构结构化程序的基本结构2. 2. 结构化程序的设计方法结构化程序的设计方法3. 3. 结构化程序的组织结构结构化程序的组织结构2021/6/491结构化程序的基本结构结构化程序的基本结构顺顺序序结结构构:是是一一种种最最简简单单、最最基基本

66、本的的结结构构,在在顺顺序序结结构构内内,各各块块按按照照它它们们出出现现的的先先后后顺顺序序依依次次执执行。它有行。它有一个入口一个入口,一个出口一个出口。选选择择结结构构:选选择择结结构构中中包包含含一一个个判判断断框框,根根据据给给定定的的条条件件是是否否成成立立而而选选择择执执行行,它它也也只只具具有有一一个个入口入口和和一个出口一个出口。循环结构循环结构:循环结构又称重复结构,是指在一定:循环结构又称重复结构,是指在一定条件下条件下反复执行反复执行一个程序块的结构。循环结构也一个程序块的结构。循环结构也是只有是只有一个入口一个入口,一个出口一个出口。2021/6/492 结构化程序的

67、设计方法结构化程序的设计方法 结结构构化化程程序序主主要要采采用用自自上上而而下下、逐逐步步细细化化的的设设计计方方法法,即即先先全全局局后后局局部部、先先整整体体后后细细节节、先先抽抽象象后后具具体体的的设设计计方方法法。由由于于实实际际问问题题往往往往比比较较复复杂杂,为为了了提提高高效效率率,在在进进行行结结构构化化程程序序设设计计时时,常常常常伴伴随随着着使使用用关关键键部部分分优优先先考考虑虑的的设设计方法。计方法。2021/6/493 结构化程序的组织结构结构化程序的组织结构 模块模块A1模块模块A1(小功能)(小功能)模块模块A2模块模块A2(小功能)(小功能)模块模块A(较小功

68、能)(较小功能)模块模块CC1C2C3C4模块模块BB1B2主模块(主功能)主模块(主功能)图图3.1 程序模块化示意图程序模块化示意图2021/6/494 顺序结构顺序结构:顺序结构是最简单、最基本的结构,在顺序顺序结构是最简单、最基本的结构,在顺序结构内,顺序执行各个语句。结构内,顺序执行各个语句。 图图3.23.2表示了一个顺序结构形式。表示了一个顺序结构形式。例例3.123.12 ABab图3.2顺序结构示意图3.3 3.3 顺序结构程序设计顺序结构程序设计【例【例3.123.12】顺序结构程序举例(求表达式值)】顺序结构程序举例(求表达式值) #includevoid main( )

69、 int a,b,result; couta; cinb; result=3*a-2*b+1; cout“result is ”resultendl; 程序的运行结果为:程序的运行结果为: please input two number: 123 45 result is 2802021/6/495 在在C+C+语言中,实现顺序结构除了一般的语句如表达式语句、语言中,实现顺序结构除了一般的语句如表达式语句、输入输出函数的调用语句外,还有两种特殊形式的语句:空输入输出函数的调用语句外,还有两种特殊形式的语句:空语句和复合语句。语句和复合语句。空空语语句句:C+C+语语言言中中,只只有有一一个个分

70、分号号的的语语句句称称为为空空语语句句,即即:; 它它在在语语法法上上要要占占据据一一个个语语句句的的位位置置,但但它它没没有有任任何何功功能能操操作。作。复复合合语语句句:复复合合语语句句是是由由花花括括号号 括括起起来来的的多多个个语语句句组组成成,在语法上它等价于一个语句,一般形式为:在语法上它等价于一个语句,一般形式为: 语句语句1;1; 语句语句2; 2; 语句语句n n 程序举例程序举例:例:例3.133.13、例、例3.143.14、例、例3.153.15、例、例3.163.16。3.3 3.3 顺序结构程序设计顺序结构程序设计2021/6/4963.4 3.4 选择结构的实现选

71、择结构的实现3.4.1 3.4.1 用用if 语句实现选择结构设计语句实现选择结构设计3.4.23.4.2 用用switch语句实现选择结构设计语句实现选择结构设计2021/6/497基本形式一基本形式一: if( (表达式表达式) ) 语句语句; ; 其执行过程是其执行过程是: :首先计算表达式的值,若不为首先计算表达式的值,若不为0 0,条件判断为真,则执行,条件判断为真,则执行( ) ( ) 后面的语句,否则,后面的语句,否则,不执行不执行( )( )后面的语句。后面的语句。 基本形式二:基本形式二: if ( (表达式表达式) ) 语句语句1;1; else 语句语句2;2; 其执行过

72、程是:其执行过程是:首先计算表达式的值,若不为首先计算表达式的值,若不为0 0,条件判断为真,则执行语句,条件判断为真,则执行语句1 1,否则执行语句,否则执行语句2 2。ifif语句的基本形式语句的基本形式2021/6/498例例3.17 输入两个数输入两个数a,b,a,b,输出其中的大数输出其中的大数( ( 用用if ) 。#include void main( ) int a,b,x; cinab; x=b; if(ab) x=a; coutxendl; #include void main( ) int a,b,x; cinab; if(ab) x=a; else x=b; coutx

73、endl; 例例3.18 用用 if-else 结构形式改写上例。结构形式改写上例。2021/6/499F一般形式一般形式( (常用常用):): if ( (表达式表达式1)1) 语句语句1;1; else if ( (表达式表达式2)2) 语句语句2;2; else if ( (表达式表达式3)3) 语句语句3;3; else if ( (表达式表达式n)n) 语句语句n;n; else 语句语句n+1;n+1;例例3.19 if语句嵌套的使用。语句嵌套的使用。ifif语句的嵌套语句的嵌套2021/6/4100真真假假真真真真真真假假假假假假表达式表达式1 1表达式表达式2 2表达式表达式3

74、 3表达式表达式4 4语句语句1 1语句语句2 2语句语句3 3语句语句4 4语句语句5 5ifif语句的嵌套示意图语句的嵌套示意图2021/6/4101F其他形式其他形式: : if ( ) if( ) 语句语句1; else 语句语句2; if ( ) if ( ) 语句语句1; else 语句语句2; If ( ) if ( ) 语句语句1; else 语句语句2; else 语句语句3;例例3.20 编写一程序计算编写一程序计算函数函数( (用用if-else嵌套嵌套) )。ifif语句的嵌套语句的嵌套2021/6/4102 switch switch语句实现选择结构语句实现选择结构F

75、C+C+C+C+语语言言提提供供了了switch语语句句可可用用来来直直接接处处理理多多分分支支选选择择问问题题,其流程图其流程图 语句组语句组1break;语句组语句组2break;语句组语句组nbreak;缺省语句组缺省语句组表达式表达式case常量常量1case常量常量2case常量常量ndefault2021/6/4103FSwitchSwitch 语句又称为语句又称为语句又称为语句又称为开关分支语句开关分支语句开关分支语句开关分支语句,它的一般形式如下:,它的一般形式如下:,它的一般形式如下:,它的一般形式如下: switchswitch( ( ( (表达式表达式表达式表达式) )

76、) ) case case 常量表达式常量表达式常量表达式常量表达式1 1 1 1: : 语句组语句组语句组语句组1 1 1 1; ; breakbreak; ; casecase 常量表达式常量表达式常量表达式常量表达式2:2:2:2: 语句组语句组语句组语句组2; 2; 2; 2; breakbreak; ; ; ; casecase 常量表达式常量表达式常量表达式常量表达式n:n:n:n: 语句组语句组语句组语句组n;n;n;n; breakbreak; ; ; ; defaultdefault : : : : 语句组语句组语句组语句组n+1n+1n+1n+1; 例例.21。 switc

77、h switch语句实现选择结构语句实现选择结构2021/6/4104Fswitchswitch允许多个允许多个case共同使用一个语句组,其结构为:共同使用一个语句组,其结构为: switchswitch( (表达式表达式) ) casecase 常量表达式常量表达式1 1: : : : casecase 常量表达式常量表达式m m: : : : 语句组语句组语句组语句组m;m;m;m; break; ; ; ; case case 常量表达式常量表达式m+1:m+1: 语句组语句组m+1; m+1; break; ; casecase 常量表达式常量表达式n:n: 语句组语句组n;n; b

78、reak; ; defaultdefault : : 语句组语句组n+1;n+1; switch switch语句实现选择结构语句实现选择结构例例3.222021/6/4105#include void main( )char grade;coutgrade;if(grade=a&grade=z)grade-=32;switch(grade) caseA: caseB: caseC:coutpassn;break; caseD:coutfailn; break; default:couterrorn; 2021/6/4106实习实习实习实习4 4 4 4、5 5 5 5:1.1.顺序结构程序设

79、计顺序结构程序设计: : P253 P253 实验一实验一:1:14 42.2.选择结构程序设计:选择结构程序设计: P253 P253 实验二:实验二:3 3、4 4顺序结构与选择结构程序设计顺序结构与选择结构程序设计2021/6/41073.5 3.5 循环结构程序设计循环结构程序设计v循环结构循环结构:循环结构又称重复结构,是指在:循环结构又称重复结构,是指在一定条件下反复执行一个程序块的结构。循一定条件下反复执行一个程序块的结构。循环结构也是只有环结构也是只有一个入口一个入口,一个出口一个出口。根据根据循环条件的不同,循环结构分为当型循环结循环条件的不同,循环结构分为当型循环结构和直到

80、型循环结构两种。构和直到型循环结构两种。2021/6/41083.5 3.5 循环结构程序设计循环结构程序设计v循环结构循环结构:循环结构又称重复结构,是指在:循环结构又称重复结构,是指在一定条件下反复执行一个程序块的结构。循一定条件下反复执行一个程序块的结构。循环结构也是只有环结构也是只有一个入口一个入口,一个出口一个出口。根据根据循环条件的不同,循环结构分为当型循环结循环条件的不同,循环结构分为当型循环结构和直到型循环结构两种。构和直到型循环结构两种。A条件PabYN图3.6 当型循环结构流程图图3.7直到型循环结构流程图abNY条件PA当型循环的结构当型循环的结构当型循环的结构当型循环的

81、结构:当给定的条件当给定的条件p p成立时,执行成立时,执行A A框操作,框操作,执行完执行完A A操作后,再判断操作后,再判断p p条件是否成立,如果成立,再次执行条件是否成立,如果成立,再次执行A A操作,如此重复执行操作,如此重复执行A A操作,直到判断操作,直到判断p p条件不成立才停止循环。条件不成立才停止循环。此时不执行此时不执行A A操作,而从出口操作,而从出口b b脱离循环结构。脱离循环结构。直到型循环的结构直到型循环的结构:先执行先执行A A框操作,然后判断给定条件框操作,然后判断给定条件p p是否成立,如果不成立,再次执行是否成立,如果不成立,再次执行A A操作;然后再对操

82、作;然后再对p p进行判断,进行判断,如此反复,直到给定的如此反复,直到给定的p p条件成立为止。此时不再执行条件成立为止。此时不再执行A A框,从出框,从出口口b b脱离循环。脱离循环。2021/6/4109 一个循环结构应由四个主要部分构成一个循环结构应由四个主要部分构成: : 循循循循环环环环的的的的工工工工作作作作部部部部分分分分。即即即即循循循循环环环环体体体体,完完完完成成成成循循循循环环环环程程程程序序序序的主要工作。的主要工作。的主要工作。的主要工作。 循循循循环环环环的的的的修修修修改改改改部部部部分分分分。它它它它保保保保证证证证循循循循环环环环体体体体在在在在循循循循环环

83、环环过过过过程程程程中,有关的量能按一定的规律变化(中,有关的量能按一定的规律变化(中,有关的量能按一定的规律变化(中,有关的量能按一定的规律变化(循环变量循环变量循环变量循环变量)。)。)。)。 循循循循环环环环的的的的控控控控制制制制部部部部分分分分。它它它它保保保保证证证证循循循循环环环环程程程程序序序序按按按按规规规规定定定定的的的的循环条件控制循环正确进行(循环条件控制循环正确进行(循环条件控制循环正确进行(循环条件控制循环正确进行(循环条件循环条件循环条件循环条件)。)。)。)。 循循循循环环环环的的的的初初初初始始始始部部部部分分分分。它它它它是是是是保保保保证证证证循循循循环环

84、环环结结结结构构构构能能能能够够够够开开开开始始始始执执执执行行行行的的的的语语语语句句句句,往往往往往往往往编编编编写写写写在在在在程程程程序序序序的的的的开开开开头头头头部部部部分分分分,逻逻逻逻辑辑辑辑上上上上先从这一部分开始执行(先从这一部分开始执行(先从这一部分开始执行(先从这一部分开始执行(初始条件初始条件初始条件初始条件)。)。)。)。 2021/6/41103.5.13.5.1 while语句语句3.5.23.5.2 do- -while语句语句3.5.33.5.3 for语句语句3.5.43.5.4 跳转语句跳转语句break和和continue3.5.53.5.5 循环的嵌

85、套循环的嵌套3.5 3.5 循环结构程序设计循环结构程序设计2021/6/41113.5.1 while 3.5.1 while 语句语句 一般形式一般形式: while( (表达式表达式) ) 语句语句; ; /循环体循环体循环体循环体执执行行过过程程: :首首先先判判断断括括号号内内最最初初表表达达式式的的值值,如如为为0 0则则跳跳到到循循环环体体外外;如如为为非非0 0,就就执执行行语语句句( (循循环环体体) ),执执行行完完循循环环体体后后再再次次判判断断表表达达式式的的值值,如如此此反反复复进进行行直直到到( (表表达达式式) )的的值值为为假假假假时时结结束束while循循环。

86、环。 2021/6/4112 例例3.23 3.23 编写程序计算编写程序计算1+2+3+.+99+1001+2+3+.+99+100 #include void main( ) int sum,n; n=1; /初始部分初始部分初始部分初始部分( ( ( (初始条件初始条件初始条件初始条件) ) ) ) sum=0; while(n=100) /控制部分控制部分控制部分控制部分( ( ( (循环条件循环条件循环条件循环条件) ) ) ) /工作部分工作部分工作部分工作部分( ( ( (循环体循环体循环体循环体) ) ) ) sum+=n; n+; /修改部分修改部分修改部分修改部分( ( (

87、 (循环变量循环变量循环变量循环变量) ) ) ) coutsum=sumendl; 运行结果为:运行结果为:sum=50502021/6/4113 #include#include voidvoid main( ) main( ) intint x,c1=0,c2=0; x,c1=0,c2=0; cout“ cout“请输入一个正整数请输入一个正整数请输入一个正整数请输入一个正整数(=0(x; cinx; whilewhile(x0)(x0) if if(x60) c1+;(x60) c1+; else else c2+; c2+; cout“ cout“请输入一个正整数请输入一个正整数请输

88、入一个正整数请输入一个正整数(=0(x; cinx; cout“ cout“小于小于小于小于6060的正整数个数:的正整数个数:的正整数个数:的正整数个数:”c1endl; ”c1endl; cout“ cout“大于大于大于大于6060的正整数个数:的正整数个数:的正整数个数:的正整数个数:”c2endl;”c2endl; 例例例例3.24 3.24 3.24 3.24 分别统计出键入的所有正整数中分别统计出键入的所有正整数中分别统计出键入的所有正整数中分别统计出键入的所有正整数中606060=60=60=60=60的数据的个数。的数据的个数。的数据的个数。的数据的个数。2021/6/411

89、43.5.2 do-while 3.5.2 do-while 语句语句 一般形式:一般形式:一般形式:一般形式: do 语句语句; ; /循环体循环体循环体循环体 while ( (表达式表达式) ); ; ; ; do-whiledo-while与与与与whilewhile比比比比较较较较:do-while语语句句是是先先执执行行循循环环体体,再再进进行行判判断断,无无论论条条件件是是否否成成立立,do-while语语句句至至少少执执行行循循环环体体一一次次,它它是是直直直直到到到到型型型型循循循循环环环环。而而while语语句句则则要要先先对对条条件件进进行行判判断断,只只有有当当条条件件

90、成成立立才才执执行行循循环环体体,因因此此它它是是当当当当型型型型循循循循环环环环。对对于于一一个个循循环环问问题题,我我们们既既可可以以用用当当型型循循环环也也可可以以用用直到型循环来解决问题。直到型循环来解决问题。2021/6/4115 #include /用用用用do-whiledo-whiledo-whiledo-while结构结构结构结构 void main( ) int sum,n; n=1; /初始部分初始部分初始部分初始部分( ( ( (初始条件初始条件初始条件初始条件) ) ) ) sum=0; do /工作部分工作部分工作部分工作部分( ( ( (循环体循环体循环体循环体)

91、 ) ) ) sum+=n; n+; /修改部分修改部分修改部分修改部分( ( ( (循环变量循环变量循环变量循环变量) ) ) ) while(n=100) ; /控制部分控制部分控制部分控制部分( ( ( (循环条件循环条件循环条件循环条件) ) ) ) coutsum=sumendl; 例例3.25 3.25 编写程序计算编写程序计算1+2+3+.+99+100 1+2+3+.+99+100 2021/6/41163.5.3 for 3.5.3 for 语句语句一般形式:一般形式:一般形式:一般形式: for( (表达式表达式1 1; ; 表达式表达式2 2; ; 表达式表达式3) 3)

92、 语句语句; ; /循环体循环体循环体循环体 说明:说明:说明:说明: 三个表达式的作用:三个表达式的作用:三个表达式的作用:三个表达式的作用:表达式表达式1 1一般用来一般用来初始化初始化初始化初始化循环控制变量;循环控制变量;表达式表达式2 2为表示为表示循环条件循环条件循环条件循环条件的表达式,用作循环控制条件,其作的表达式,用作循环控制条件,其作用与前两类循环语句中的表达式完全一样,用法也基本相同;用与前两类循环语句中的表达式完全一样,用法也基本相同;表达式表达式3 3用来修改用来修改循环控制变量循环控制变量循环控制变量循环控制变量,用以表示循环控制变量的增,用以表示循环控制变量的增量

93、或减量,常用自增或自减运算量或减量,常用自增或自减运算( (注意注意注意注意:三表达式必须用分号:三表达式必须用分号隔开隔开) )。 语句语句语句语句: : : :不仅可以是单个语句,也可以是复合语句或空语句。不仅可以是单个语句,也可以是复合语句或空语句。执行过程:执行过程:执行过程:执行过程:先计算表达式先计算表达式1 1的值,接着计算表达式的值,接着计算表达式2 2的值并判的值并判断,若表达式断,若表达式2 2的值的值非零非零非零非零则执行循环体的语句,然后计算表达则执行循环体的语句,然后计算表达式式3 3的值,再从计算表达式的值,再从计算表达式2 2 的值开始下一次循环,重复这种的值开始

94、下一次循环,重复这种先计算判断,后执行再计算的过程,直到某次先计算判断,后执行再计算的过程,直到某次( (也可能是第一也可能是第一次次) )表达式表达式表达式表达式2 2 2 2的值为零时结束循环。的值为零时结束循环。的值为零时结束循环。的值为零时结束循环。2021/6/4117 例例3.26 3.26 编写程序计算编写程序计算1+2+3+.+99+100 1+2+3+.+99+100 #include /用用用用forforforfor结构结构结构结构void main( ) int sum,n; sum=0; for (n=1; n=100; n+) sum+=n; coutsum=sum

95、endl; n=1; while(n=100) sum+=n; n+; 2021/6/4118for( ( 表达式表达式1; 表达式表达式2; 表达式表达式3 ) 说明:说明:说明:说明: 三个表达式的类型:三个表达式的类型:三个表达式的类型:三个表达式的类型:表达式表达式2 2一般是关系表达式或逻一般是关系表达式或逻辑表达式,但也可是数值表达式或字符表达式,即辑表达式,但也可是数值表达式或字符表达式,即可是任意表达式,只要其值为非零,就执行循环体。可是任意表达式,只要其值为非零,就执行循环体。表达式表达式1 1和表达式和表达式3 3一般为简单表达式一般为简单表达式( (赋值、自增、赋值、自增

96、、自减表达式自减表达式) ),但也可以使用,但也可以使用逗号表达式逗号表达式逗号表达式逗号表达式,可一次完,可一次完成对多个变量赋初值和修改多个变量的功能,成对多个变量赋初值和修改多个变量的功能, 例如:例如: for (i=0, j=100; ij; i+, j- -) k=i+j;2021/6/4119 例例3.27 3.27 逗号表达式使用实例逗号表达式使用实例 #include /用用用用forforforfor结构结构结构结构void main( ) int sum,n; for (sum=0, n=1; n=100; n+) sum+=n; coutsum=sumendl; for

97、 (sum=0, n=1; n=100; sum+=n, n+) ; 逗号运算符可以将多个表达式连接起来,其功能是从左向右逗号运算符可以将多个表达式连接起来,其功能是从左向右求解各个表达式,而整个表达式的值为最后求解的表达式的值。求解各个表达式,而整个表达式的值为最后求解的表达式的值。用逗号连接起来的表达式称为逗号表达式。逗号表达式的一般形用逗号连接起来的表达式称为逗号表达式。逗号表达式的一般形式是:表达式式是:表达式1 1,表达式,表达式2 2,表达式,表达式n n 逗号运算符的优先级最低,并且具有左结合性。比如,逗号逗号运算符的优先级最低,并且具有左结合性。比如,逗号表达式表达式3+5,

98、6+73+5, 6+7的值是的值是1313。逗号表达式在。逗号表达式在C+C+程序中用途比较少,程序中用途比较少,通常只用于通常只用于forfor循环语句中。循环语句中。2021/6/4120说明:说明:三个表达式的省略使用:三个表达式的省略使用:for允许省略或部分允许省略或部分省略三个表达式,但用作分隔符的省略三个表达式,但用作分隔符的两个分号绝两个分号绝不能省略。不能省略。以以下是下是省略表达式省略表达式的几种情况的几种情况: :for( ( 表达式表达式1; 表达式表达式2; 表达式表达式3 ) 省略表达式省略表达式1 1 此时应在此时应在for语句前给循环变量赋初值。语句格式为:语句

99、前给循环变量赋初值。语句格式为: for ( ; ; 表达式表达式2 ; ; 表达式表达式3 ) 语句语句;#include void main( ) int sum,n; sum=0; n=1; for(; n=100; n+) sum+=n; coutsum=sumendl; 2021/6/4121说明:说明:三个表达式的省略使用:三个表达式的省略使用:for允许省略或部分允许省略或部分省略三个表达式,但用作分隔符的省略三个表达式,但用作分隔符的两个分号绝两个分号绝不能省略。不能省略。for( ( 表达式表达式1; 表达式表达式2; 表达式表达式3 ) 省略表达式省略表达式 2 2 此时循

100、环条件永远为真,必须在循环体中有跳出循环的控制此时循环条件永远为真,必须在循环体中有跳出循环的控制条件语句,否则构成死循环。条件语句,否则构成死循环。 语句格式为:语句格式为: for ( 表达式表达式1 ; ; ; 表达式表达式3 ) 语句语句;#include void main( ) int sum,n; sum=0; for(n=1; ;n+) if(n100) break; sum+=n; coutsum=sumendl; 2021/6/4122说明:说明:三个表达式的省略使用:三个表达式的省略使用:for允许省略或部分允许省略或部分省略三个表达式,但用作分隔符的省略三个表达式,但用

101、作分隔符的两个分号绝两个分号绝不能省略。不能省略。for( ( 表达式表达式1; 表达式表达式2; 表达式表达式3 ) 省略表达式省略表达式 3 3 此时需在循环体内使循环控制变量递变,以保证循环正常结此时需在循环体内使循环控制变量递变,以保证循环正常结束。束。 语句格式为:语句格式为: for ( 表达式表达式1 ; ; 表达式表达式2 ; ; ) 语句语句 ;#include void main( ) int sum,n; sum=0; for(n=1; n=100; ) sum+= n+; coutsum=sumendl; 2021/6/4123说明:说明:三个表达式的省略使用:三个表达

102、式的省略使用:for允许省略或部分允许省略或部分省略三个表达式,但用作分隔符的省略三个表达式,但用作分隔符的两个分号绝两个分号绝不能省略。不能省略。for( ( 表达式表达式1; 表达式表达式2; 表达式表达式3 ) 2 2个或个或3 3个表达式均可省略个表达式均可省略 此时需要预先赋初值,在循环体内修改循环变量的值,在循此时需要预先赋初值,在循环体内修改循环变量的值,在循环体中有跳出循环的控制条件语句。环体中有跳出循环的控制条件语句。 这种格式完全等价于这种格式完全等价于 while (1) 的语句格式。的语句格式。#include void main( ) int sum, n; sum=

103、0; n=1; for ( ; ; ) if(n100) break; sum+=n+; coutsum=sumendl; 2021/6/41243.5.4 break 3.5.4 break 语句和语句和continuecontinue语句语句 在在实实际际应应用用中中,break语语句句一一般般都都是是与与if条条件件语语句句配配合合使使用用。break语语句句也也被被称称为为中中断断语语句句。该该语语句句被被限限定定使使用用在在任任一一种种循循环环语语句句和和switch语语句句中中,当当程程序序执执行行到到该该语语句句时时,将将立立即即结结束束所所在在循循环环语语句句或或switch语

104、句的执行,接着执行其后面的语句。语句的执行,接着执行其后面的语句。 break语句也可以用于嵌套的循环结构中,在这语句也可以用于嵌套的循环结构中,在这种情况下,如执行种情况下,如执行break则仅仅退出包含该则仅仅退出包含该break语语句的句的那层循环那层循环,即,即break语句不能使程序控制退出一语句不能使程序控制退出一层以上的循环。层以上的循环。 TRUE bodystatementExpressionFALSE statement1; break; break; statementn;break;break;2021/6/4125 #include void main( ) doub

105、le a,c=100000000.00; /c/c/c/c代表已知的当前产值代表已知的当前产值代表已知的当前产值代表已知的当前产值; ; ; ; for( ; ; ) /等价等价等价等价 于于于于while(1) while(1) while(1) while(1) int year=0; /y/y/y/y代表所要求的年数代表所要求的年数代表所要求的年数代表所要求的年数 couta; /a/a/a/a代表增长率代表增长率代表增长率代表增长率 if(a=2*c ) break; cout增长率为增长率为a 时产值增长一倍所需年时产值增长一倍所需年yearendl; 例例例例3 3 3 3.28

106、.28 .28 .28 已知产值及产值增长速度,编写计算产值已知产值及产值增长速度,编写计算产值已知产值及产值增长速度,编写计算产值已知产值及产值增长速度,编写计算产值 增长一倍所需的年数的程序。增长一倍所需的年数的程序。增长一倍所需的年数的程序。增长一倍所需的年数的程序。 运行结果:运行结果: 请输入增长率:请输入增长率:0.20.2 增长率为增长率为0.20.2时产值增长一倍所需年数为:时产值增长一倍所需年数为:4 4 请输入增长率:请输入增长率:002021/6/4126continue continue 语句语句 continue 语句也用于循环结构中,它的语句也用于循环结构中,它的作

107、用作用作用作用是忽略是忽略它之后到循环终止的程序,而它之后到循环终止的程序,而转向下一次循环转向下一次循环转向下一次循环转向下一次循环。和和break 语句一样,语句一样,continue 语句通常也是和语句通常也是和 i if 语语句结合,一同使用于循环结构中。句结合,一同使用于循环结构中。 continue 和和break 的作用有相似之处,却有着根本的作用有相似之处,却有着根本区别,区别,continue 语句只是结束语句只是结束本次循环本次循环本次循环本次循环,还要进行,还要进行下一次循环,而不是要结束整个循环下一次循环,而不是要结束整个循环; ;break 则是结则是结束束整个循环整

108、个循环整个循环整个循环,转到循环体外面去了。,转到循环体外面去了。 TRUE bodystatementExpressionFALSE statement1; continue;continue; statementn;continue;continue;2021/6/4127 #include void main( ) int i, count=0; for ( i=100; i=150; +i ) if ( i%3=0 ) contiune; cout i “ ”; count + ; if (count%5=0 ) coutendl; /一行输出一行输出5 5个数据个数据 cout en

109、dl; 例例例例3.29 3.29 3.29 3.29 将将将将100100100100150150150150之间不能被之间不能被之间不能被之间不能被3 3 3 3整除的数输出。整除的数输出。整除的数输出。整除的数输出。 程序的运行结果为:程序的运行结果为:1001011031041061071091101121131151161181191211221241251271281301311331341361371391401421431451461481492021/6/41283.5.5 3.5.5 循环的嵌套循环的嵌套 一个循环体内包含另一个完整的循环结构称为一个循环体内包含另一个完整的

110、循环结构称为循环循环循环循环的嵌套的嵌套的嵌套的嵌套,内嵌的循环中还可以嵌套循环,这就是多,内嵌的循环中还可以嵌套循环,这就是多重循环。三种循环可以互相嵌套,但在循环的嵌套重循环。三种循环可以互相嵌套,但在循环的嵌套中要中要注意注意注意注意,内层循环应完全在外层循环里面,也就,内层循环应完全在外层循环里面,也就是是不允许出现交叉不允许出现交叉不允许出现交叉不允许出现交叉。在嵌套的循环结构中,如用缺口矩形表示每层循环在嵌套的循环结构中,如用缺口矩形表示每层循环结构时,则结构时,则图图3 3.8.8中中(a)(b)(a)(b)是正确的多层循环结构,是正确的多层循环结构,而而(c)(c)是错误的多层

111、循环结构,因为它出现了循环是错误的多层循环结构,因为它出现了循环结构的交叉。结构的交叉。另外,使用循环结构时另外,使用循环结构时必须注意必须注意必须注意必须注意,如果循环的控制,如果循环的控制条件永远成立,循环体将永无休止地反复执行,程条件永远成立,循环体将永无休止地反复执行,程序就将陷入序就将陷入“死循环死循环死循环死循环”,这显然是应当防止的。,这显然是应当防止的。2021/6/4129 例例3.35 3.35 实现打印九九乘法表实现打印九九乘法表。 1*1= 1 1*2= 2 2*2= 4 1*3= 3 2*3= 6 3*3= 9 1*4= 4 2*4= 8 3*4=12 4*4=16

112、1*5= 5 2*5=10 3*5=15 4*5=20 5*5=25 1*6= 6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 1*7= 7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 1*8= 8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 1*9= 9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81ij1.i1:92021/6/4130#include#includevoid main()int i, j,

113、result;i=1;j=1;cout九九乘法表:九九乘法表:n;while (i=9) j=1; while (j=i) result=i*j; coutj+*i= setw(2)result ; i+; coutn;上机实习上机实习上机实习上机实习: 要求改为要求改为要求改为要求改为 for for 循环实现循环实现循环实现循环实现2021/6/4131实习实习实习实习6 6 6 6:1.1.1.1.假设我国现在人口假设我国现在人口假设我国现在人口假设我国现在人口14141414亿,若年增长率为亿,若年增长率为亿,若年增长率为亿,若年增长率为1.2% 1.2% 1.2% 1.2% ,度计算

114、多少年,度计算多少年,度计算多少年,度计算多少年后我国人口增加到或超过后我国人口增加到或超过后我国人口增加到或超过后我国人口增加到或超过20202020亿。亿。亿。亿。2.2.2.2.分别用分别用分别用分别用3 3 3 3种循环结构种循环结构种循环结构种循环结构(whilewhilewhilewhile、do-whiledo-whiledo-whiledo-while、forforforfor)求求求求n!n!n!n!,n n n n值由值由值由值由键盘键入。键盘键入。键盘键入。键盘键入。3.3.3.3.输出以下图形:输出以下图形:输出以下图形:输出以下图形:循环结构程序设计循环结构程序设计

115、* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *2021/6/4132 例例1 1 输出输出100100以内的所有素数。以内的所有素数。 3.6 3.6 程序设计举例(习题课)程序设计举例(习题课)读入读入mk= mi=2当当i km被被i整除整除真真假假用用break结束循环结束循环i=i+1i k+1真真假假输出输出:m”是素数是素数”输出输出:m”不不是素数是素数”算法分析算法分析: 判断一个数判断一个数m是否是素数的算是否是素数的算法如下:让法如下:让m被被2到到 之中的整之中的整数除数除,如

116、果如果m能被这些数之中的任能被这些数之中的任何一个整除何一个整除,则说明则说明m不是素数;不是素数;否则否则m是素数。是素数。 对对100以内的每一个自然数进以内的每一个自然数进行素数的判断,若是则输出之。行素数的判断,若是则输出之。 上述步骤上述步骤用一个内循环实现,用一个内循环实现,步骤步骤用一个外循环实现。用一个外循环实现。/ i=2k注意退出注意退出循环的两循环的两种情况:种情况:2021/6/4133x3.6 3.6 程序设计举例(习题课)程序设计举例(习题课)介绍几个常用的数学函数介绍几个常用的数学函数:int abs(int x); | x |double fabs(double

117、 x); double log(doubel x); ln(x)double log10(double x); log10(x) double exp(double x); exdouble pow(double x, double y); xydoubel sqrt(double x); 2021/6/4134#include #include #include void main( ) int m, i, k, count=0; for (m=2; m=100; m+ ) / m/ m为为2 2100100内的整数内的整数 k=sqrt(m+1); /加加1 1是为避免在求是为避免在求 可

118、能出现的误差可能出现的误差 for (i=2; i = k+1 ) cout setw(4) m; count+; if (count %5 = = 0 ) coutendl; 程序的运行结果为:程序的运行结果为:23571113171923293137414347535961677173798389972021/6/4135 例例例例2 2 2 2 求两个整数的最大公约数求两个整数的最大公约数求两个整数的最大公约数求两个整数的最大公约数开始开始开始开始nm?nm?结束结束结束结束真真真真假假假假n,mn,m互换互换互换互换r=n%mr=n%mn=m; m=r;n=m; m=r;输入输入输入输

119、入m,nm,nr!=0?r!=0?输出输出输出输出mm假假假假真真真真r=n%mr=n%m#include#includevoid main() int n,m,r,temp;cout请输入两个正整数请输入两个正整数nm;if (nm) temp=n; n=m; m=temp; r =n%m;while(r!=0) n=m; m=r; r=n%m;cout最大公约数为最大公约数为:m=3n=3),即从第),即从第3 3个数开始,每个数等于前个数开始,每个数等于前2 2个数之和。个数之和。153423315971094675025514229352457824157817185537725841

120、7711121393832040570288739088169213896104181286571964181346269922746563245986321144987676546368317811217830914930352102334155新新新新f 1f 1f 2f 2f 1f 1新新新新f 2f 2算法分析:算法分析:2021/6/4137 例例例例3 3 3 3 求求求求FibonacciFibonacciFibonacciFibonacci数列的前数列的前数列的前数列的前40404040个数个数个数个数#include #include void main() long int

121、 f1=1, f2=1; /*/*定义并初始化数列的头定义并初始化数列的头2 2个数个数*/*/ int i; for(i=1; i=20; i+ ) /*1/*1组组2 2个,个,2020组组4040个数个数*/*/ coutsetw(12)f1setw(12)f2; /*/*输出当前的输出当前的2 2个数个数*/*/ if (i%2=0) coutendl; f1=f1+ f2; f2=f2+f1; 迭代思想迭代思想2021/6/4138 例例例例4 4 4 4 求求求求1!+2!+10!1!+2!+10!1!+2!+10!1!+2!+10! 循环结构中,最常用的算法就是累加和累乘。一般累

122、循环结构中,最常用的算法就是累加和累乘。一般累加和累乘是通过循环结构和循环体内的一句表示累加性或加和累乘是通过循环结构和循环体内的一句表示累加性或累乘性语句来实现的。我们通常把程序中累乘性语句来实现的。我们通常把程序中 sum sum 变量称为变量称为累加器累加器、fact fact 变量称为变量称为累乘器累乘器。要注意,。要注意,sumsum的初值赋的初值赋为为0 0,而,而factfact的初值赋为的初值赋为1 1。另外,赋初值的操作一定要在。另外,赋初值的操作一定要在循环结构外进行。循环结构外进行。 本例要用一个双循环来实现,外循环用来求累加,内本例要用一个双循环来实现,外循环用来求累加

123、,内循环用来求累乘。循环用来求累乘。 2021/6/4139 例例例例4 4 4 4 求求求求1!+2!+10!1!+2!+10!1!+2!+10!1!+2!+10!#include using namespace std;void main()long int sum, fact , i, j;sum=0;for(i=1;i=10;i+) fact=1; for(j=1;j=i;j+) fact=fact*j; sum=sum+fact;coutsumendl;练习练习练习练习: 去除内循环完成该题。去除内循环完成该题。去除内循环完成该题。去除内循环完成该题。2021/6/4140 例例例例

124、5 5 5 5 求自然对数求自然对数求自然对数求自然对数e e e e的近似值的近似值的近似值的近似值 求自然对数求自然对数e的近似值的近似值, 要求使其误差小于要求使其误差小于10 - 6,近似公式为,近似公式为:题目分析:题目分析: (1) (1) 依据近似公式,应该先求第依据近似公式,应该先求第i i项的阶乘,再将各项阶项的阶乘,再将各项阶乘的倒数进行累加。因此程序中设计两个变量乘的倒数进行累加。因此程序中设计两个变量sumsum和和factfact分别分别作为累加器和累乘器。另外,要考虑数据的精度问题。为防止作为累加器和累乘器。另外,要考虑数据的精度问题。为防止项数过大时阶乘溢出,定义

125、项数过大时阶乘溢出,定义factfact为为doubledouble类型;类型;sumsum也定义为也定义为doubledouble类型类型, ,是为满足题目的求值精度要求。是为满足题目的求值精度要求。 (2) (2)如何判断循环结束。由于循环次数不确定,所以用如何判断循环结束。由于循环次数不确定,所以用whilewhile循环好一些。循环好一些。2021/6/4141 例例例例5 5 5 5 求自然对数求自然对数求自然对数求自然对数e e e e的近似值的近似值的近似值的近似值#include using namespace std;void main() int i=1; double s

126、um=0, fact=1; while( 1/fact=0.0000001) sum = sum + 1/fact; i+; fact = fact * i; coutesumendl; 上机练习:上机练习:上机练习:上机练习:1. 1.2. 2. 公式求公式求公式求公式求 的近似值,直到最后一项的近似值,直到最后一项的近似值,直到最后一项的近似值,直到最后一项的绝对值小于的绝对值小于的绝对值小于的绝对值小于1010-6-6为止。为止。为止。为止。当当当当 n=20 n=20,或最后一项小于,或最后一项小于,或最后一项小于,或最后一项小于1010-3-32021/6/4142 例例例例6 6

127、6 6 百钱买百鸡百钱买百鸡百钱买百鸡百钱买百鸡 这是一个用这是一个用“穷举法穷举法”解题的典型问题。解题的典型问题。 “ “穷举法穷举法”也也称为称为“枚举法枚举法”或或“试凑法试凑法”,即将可能出现的各种情况一一,即将可能出现的各种情况一一测试,判断是否满足条件,一般采用循环来实现。测试,判断是否满足条件,一般采用循环来实现。 百元买百鸡问题。假定小鸡每只百元买百鸡问题。假定小鸡每只5 5角,公鸡每只角,公鸡每只2 2元,母元,母鸡每只鸡每只3 3元。现在有元。现在有100100元钱要求买元钱要求买100100只鸡,编程列出所有可只鸡,编程列出所有可能的购鸡方案。能的购鸡方案。 设母鸡、公

128、鸡、小鸡各为设母鸡、公鸡、小鸡各为x x、y y、z z只,根据题目要求,列只,根据题目要求,列出方程为:出方程为: x + y + z = 100x + y + z = 100 3x + 2y + 0.5z = 100 3x + 2y + 0.5z = 100三个未知数,两个方程,此题有若干个解。解决此类问题采三个未知数,两个方程,此题有若干个解。解决此类问题采用用“试凑法试凑法”,把每一种情况都考虑到。,把每一种情况都考虑到。 2021/6/4143#include #include using namespace std;void main() int x, y, z; for (x=0

129、; x=100; x+)for (y=0; y=100; y+) for(z=0; z=100; z+) if (x+y+z=100) & (3*x+2*y+0.5*z=100) coutsetw(5)xsetw(5) ysetw(5)zendl;方法一:方法一: 最简单三个未知数列三最简单三个未知数列三重循环来实现。重循环来实现。2021/6/4144#include #include using namespace std;void main() int x, y, z; for (x=0; x=33; x+)for (y=0; y=50; y+) if (3*x+2*y+0.5*(100

130、-x-y)=100) coutsetw(5)xsetw(5) ysetw(5)100-x-yendl;方法二:方法二: 从三个未知数的关系,从三个未知数的关系,利用两重循环来实现。利用两重循环来实现。2021/6/4145#include #include #include using namespace std;void main()int x,y,z;time_t t1, t2;t1=time(NULL );for (x=0;x=100;x+) for (y=0;y=100;y+) for(z=0;z=100;z+)if (x+y+z=100) & (3*x+2*y+0.5*z=100)

131、coutsetw(5)xsetw(5) ysetw(5)zendl;t2=time(NULL);cout“此方法用去此方法用去”difftime(t2, t1)“秒的时间秒的时间“endl;时间和日期函数时间和日期函数时间和日期函数时间和日期函数需要的头文件需要的头文件需要的头文件需要的头文件time_ttime_t是是是是中定义的与中定义的与中定义的与中定义的与时间有关的类型,使用时间有关的类型,使用时间有关的类型,使用时间有关的类型,使用long long int int 表示系统的时间。表示系统的时间。表示系统的时间。表示系统的时间。timetime( )函数返回系统的)函数返回系统的)

132、函数返回系统的)函数返回系统的当前时间,在本例中使用当前时间,在本例中使用当前时间,在本例中使用当前时间,在本例中使用NULLNULL即空指针为参数。即空指针为参数。即空指针为参数。即空指针为参数。difftime(t2, t1)difftime(t2, t1)函函函函数以秒为单位返回数以秒为单位返回数以秒为单位返回数以秒为单位返回t2-t1t2-t1的差。的差。的差。的差。2021/6/4146实习实习实习实习7 7 7 7:1. 1. 1. 1. 用用用用 for for for for 循环实现打印九九乘法表。循环实现打印九九乘法表。循环实现打印九九乘法表。循环实现打印九九乘法表。2.

133、2. 2. 2. 求两个整数的最大公约数和最小公倍数,两个整数由键求两个整数的最大公约数和最小公倍数,两个整数由键求两个整数的最大公约数和最小公倍数,两个整数由键求两个整数的最大公约数和最小公倍数,两个整数由键 盘键入。盘键入。盘键入。盘键入。3.3.3.3.结构程序设计综合实验结构程序设计综合实验公式求公式求的近似值,直到最后的近似值,直到最后一项的绝对值小于一项的绝对值小于1010-6-6为止。为止。当当 n=20 n=20,或最后一项小,或最后一项小于于10-310-34. 4. 4. 4. 用两种方法解百钱买百鸡问题,并进行时间分析。用两种方法解百钱买百鸡问题,并进行时间分析。用两种方

134、法解百钱买百鸡问题,并进行时间分析。用两种方法解百钱买百鸡问题,并进行时间分析。2021/6/4147第第3 3章章 函数函数C+语语言言程程序序设设计计教教程程第第4章章函函数数制作人:鲁莹 2021/6/4148第章函数第章函数1. 掌握函数的声明和定义、函数的调用及函数的参数传递过程;2. 掌握关键字inline的含义与使用;3. 掌握递归函数的使用;4. 掌握函数重载的使用方法;5. 掌握函数模板的使用方法;6. 了解各类系统函数,掌握常用的系统函数的使用。学习目标 C+语语言言程程序序设设计计教教程程第第4章章函函数数2021/6/4149. . 函数的定义和声明函数的定义和声明4.

135、1.1 函数的定义函数的定义函数是一个命名的程序代码块,是程序完成其操作的场所,是将功能重复的程序段抽象出来所形成一个独立的、可重复使用的功能模块。定义函数的一般格式为:定义函数的一般格式为:返回类型函数名(数据类型1参数1,数据类型2参数2,.)语句序列;形参表C+语语言言程程序序设设计计教教程程第第4章章函函数数F说明说明: :函数必须先定义才可以使用定义函数就是编写完成函数功能的程序块。2021/6/4150. . 函数的定义和声明函数的定义和声明在函数的定义中:n返返回回类类型型为函数返回值的类型,可以是系统任一基本数据类型或用户已定义的一种数据类型,它是函数执行过程中通过return

136、语句要求的返回值的类型,又称为该函函数数的的类类型型。当一个函数不需要通过return语句返回一个值时,称为无返回值函数或无类型函数,此时需要使用void作为类型名。n函函数数名名是用户为函数所起的名字,它是一个标识符,应符合C+标识符的一般命名规则,用户通过使用这个函数名和实参表可以调用该函数。n形形式式参参数数表表可以包含任意多项(可以没有),当多于一项时,前后两个参数之间必须用逗号分开。n用花括号括起来的语句序列组成了函数体,即函数所完成的具体操作,函数体一般分为3部分:第1部分为定义部分,定义函数所需要的局部常量与局局部部变变量量;第2部分为函数的功能部分,完成函数的功能;第3部分为返

137、回值部分,返回函数的结果。如果函数体中没有任何语句,该函数称作空函数。n每个函数都是一个功能独立的模块,绝不允许在一个函数体内定义另一个函数。C+语语言言程程序序设设计计教教程程第第4章章函函数数2021/6/4151. . 函数的定义和声明函数的定义和声明/*p4_1.cpp*函数的使用,对两个数取大*/#includeusingnamespacestd;int max(int x,int y)intz;z=(xy)?x:y;returnz;void main()inta,b;cinab;coutmax(a,b)endl;123456789101112131415161718C+语语言言程程

138、序序设设计计教教程程第第4章章函函数数函数定义函数定义主函数主函数函数体:函数所完成函数体:函数所完成的具体操作的具体操作运行结果运行结果运行结果运行结果:5 155 15 15152021/6/4152. . 函数的定义和声明函数的定义和声明在C+程序中,使用函数前首先需要对函数原型进行声明,告诉编译器函数的名称、类型和形式参数。在在C+中,函数原型声明原则如下:中,函数原型声明原则如下: (1)如果函数定义在先,调用在后,调用前可以不必声明;如果函数定义在后,调用在先,调用前必须声明。 (2)在程序设计中,为了使程序设计的逻辑结构清晰,一般将主要的函数放在程序的起始位置声明,这样也起到了列

139、函数目录的作用。C+语语言言程程序序设设计计教教程程第第4章章函函数数2021/6/4153在C+中,函数原型声明原则如下: (1)如果函数定义在先,调用在后,调用前可以不必声明;如果函数定义在后,调用在先,调用前必须声明。 (2)在程序设计中,为了使程序设计的逻辑结构清晰,一般将主要的函数放在程序的起始位置声明,这样也起到了列函数目录的作用。 声明函数原型的形式如下:声明函数原型的形式如下: 例如:例如: intmax(intx,inty);intmax(int,int);C+语语言言程程序序设设计计教教程程第第4章章函函数数.1.2 .1.2 函数原型的声明函数原型的声明 返回类型函数名(

140、数据类型1参数1,数据类型2参数2,.); 加上参数名会使函数的加上参数名会使函数的功能和参数更清晰。功能和参数更清晰。 2021/6/4154函数调用的一般形式为:n各实际参数表中的实际参数应与形参表中的形参一一对应,即个数相等且对应参数的数据类型相同。n函数调用是一个表达式,函数名连同括号是函数调用运算符。表达式的值就是被调函数的返回值,它的类型就是函数定义中指定的函数返回值的类型,即函数的类型。n如果函数的返回值为void,说明该函数没有返回值。 例如: coutmax(a,b)endl;C+语语言言程程序序设设计计教教程程第第4章章函函数数.1.2 .1.2 函数原型的声明函数原型的声

141、明 函数名 (参数1, 参数2,. ); 实际参数表F注意注意: : 主函数main()不需要进行原型语声明,也不允许任何函数调用它,它只由操作系统调用并返回操作系统。 2021/6/4155 当调用一个函数时,整个调用过程分为三步进行:第一步:函数调用; 将函数调用语句下一条语句的地址保存在一种称为“栈栈”的内存中空间中, 以便函数调用完后返回。将数据放到栈空间中的过程称为压栈压栈。 对实参表从后向前从后向前,依次计算出实参表达式的值,并将值压栈。 转跳到函数体处。 第二步:函数体执行,即逐条运行函数体中语句的过程。 如果函数中还定义了变量,将变量压栈。 将每一个形参以栈中对应的实参值对应的

142、实参值取代,执行函数的功能体。 将函数体中的变量、保存在栈中的实参值,依次从栈中取出,以释放栈 空间。从栈中取出数据称为出栈出栈,x出栈用pop(x)表示。第三步:返回,即返回到函数调用表达式的位置。 返回过程执行的是函数体中的return语句。C+语语言言程程序序设设计计教教程程第第4章章函函数数4.2.2 4.2.2 函数调用的执行过程函数调用的执行过程 2021/6/4156C+语语言言程程序序设设计计教教程程第第4章章函函数数4.2.2 4.2.2 函数调用的执行过程函数调用的执行过程 以函数max()为例,演示函数调用的详细过程如图4-1所示2021/6/4157C+语语言言程程序序

143、设设计计教教程程第第4章章函函数数4.2.3 4.2.3 函数参数的按值传递函数参数的按值传递 函数调用过程实际上执行了一个从参数传递-执行函数体-返回的过程。其中的函数参数传递过程的实质是将实参值通过栈空间一将实参值通过栈空间一一传送给实参的过程一传送给实参的过程,这种把实参表达式的值传送给对应的形参变量传递方式称为“按值传递按值传递”。2021/6/41584.2.3 函数参数的按值传递函数参数的按值传递 /*p4_2.cpp*函数的传值调用,将两个数交换*/#includeusingnamespacestd;void swap(int a,int b)intt;t=a,a=b,b=t;v

144、oid main()intx=7,y=11;coutx=xy=yendl;swap(x,y);coutafterswap:;coutx=xy=yendl;12345678910111213141516171819C+语语言言程程序序设设计计教教程程第第4章章函函数数函数定义函数定义传值调用传值调用 运行结果运行结果运行结果运行结果:x=7y=11afterswap:x=7y=112021/6/41594.2.4 嵌套调用嵌套调用 /*p4_3.cpp*函数的嵌套调用,求三个数中最大数和最小数的差值*/#includeusingnamespacestd;int max(int x,int y,i

145、nt z)intt;t=xy?x:y;return(tz?t:z);123456789101112C+语语言言程程序序设设计计教教程程第第4章章函函数数函数定义函数定义 在一个函数中调用其它函数叫函函数数的的嵌嵌套套。C+中函数的定义是平行的,除了main()以外,都可以互相调用。函数不可以嵌套定义,但可以嵌套调用。比如函数1调用了函数2,函数2再调用函数3,这便形成了函数的嵌套调用。2021/6/4160C+语语言言程程序序设设计计教教程程第第4章章函函数数int min(int x,int y,int z)intt;t=xy?x:y;return(tabc;coutMax-Min=dif(

146、a,b,c)0)递归可以分为直接递归调用和间接递归调用。直接递归调用直接递归调用:是在调用函数的过程中又调用该函数本身;间接递归调用间接递归调用:是在调用f1()函数的过程中调用f2()函数,而f2()中又需要调用f1()。C+语语言言程程序序设设计计教教程程第第4章章函函数数4.2.4 递归调用递归调用 2021/6/4162递归函数设计的一般形式是: C+语语言言程程序序设设计计教教程程第第4章章函函数数4.2.4 递归调用递归调用 函数类型 递归函数名f (参数x ) if(满足结束条件) 结果=初值; else 结果=含f(x-1)的表达式; 返回结果; 递归方法是从结果出发,归纳出后

147、一结果与前一结果直到初值为止存在的关系,要求通过分析得到:初值初值+ +递归函数递归函数,然后设计一个函数(递归函数),这个函数不断使用下一级值调用自身,直到结果已知处。 2021/6/41634. 2.4 2.4 递归调用递归调用 /*p4_4.cpp*函数的递归调用,求n!*/#includeusingnamespacestd;int fac(int n)intt;if(n=1)t=1;elset=n*fac(n-1);return(t);123456789101112131415C+语语言言程程序序设设计计教教程程第第4章章函函数数递归函数定义递归函数定义2021/6/41644. 2.

148、4 2.4 递归调用递归调用 void main()constintmax_n=12;/int类型数能表示的n!的最大的nintn;coutn;if(n=1&n=max_n)coutFactorialofnis:fac(n)endl;elsecoutInvalidn.C), (2, A-B), (2, C-B), (3, A-C), (1, B-A), (2, B-C), (1,A-C)。 2021/6/4167C+语语言言程程序序设设计计教教程程第第4章章函函数数分析:分析: 将n个盘子从A柱移到C柱可分解为以下3步: 4.2.4 递归调用递归调用 2021/6/41684. 2.4 2.4

149、 递归调用递归调用 /*p4_5.cpp*汉诺塔问题*/#includeusingnamespacestd;void move(int n, char source, char target)cout(n,sourcetarget)endl;void hanoi(int n,char A,char B,char C)if(n=1)move(1,A,C);elsehanoi(n-1, A, C, B);move(n,A,C);hanoi(n-1, B, A, C);1234567891011121314151617181920C+语语言言程程序序设设计计教教程程第第4章章函函数数递归函数定义递归

150、函数定义2021/6/41694. 2.4 2.4 递归调用递归调用 void main()intnum;coutnum;hanoi(num,A,B,C);21222324252627C+语语言言程程序序设设计计教教程程第第4章章函函数数递归函数调用递归函数调用运行结果运行结果运行结果运行结果:Input the number of diskes33(1, A-C)(2, A-B)(2, C-B)(3, A-C)(1, B-A)(2, B-C)(1, A-C) 2021/6/4170内联函数的定义形式如下:内联函数的定义形式如下: C+语语言言程程序序设设计计教教程程第第4章章函函数数4.3

151、4.3 内联函数内联函数 inline inline 函数类型函数类型 函数名函数名 ( (形式参数表形式参数表) ) 函数体;函数体; 内联函数:内联函数: 是是通通过过在在编编译译时时将将函函数数体体代代码码插插入入到到函函数数调调用用处处,将将调调用用函函数数的的方方式式改改为为顺顺序序执执行行方方式式来来节节省省程程序序执执行行的的时时间间开开销销,这这一一过过程程叫叫做做内内联联函函数数的的扩扩展展。因因此此,内内联联函函数数实实际上是一种际上是一种用空间换时间用空间换时间的方案。的方案。 在在内内联联函函数数扩扩展展时时也也进进行行了了实实参参与与形形参参结结合合的的过过程程:先先

152、将将实实参参名名( (而而不不是是实实参参值值) ),将将函函数数体体中中的的形形参参处处处处替替换换,然然后后搬搬到到调调用用处处。但但从从用用户户的的角角度度看看,调调用用内内联联函函数数和和一一般函数没有任何区别。般函数没有任何区别。 2021/6/4171. .3 3 内联函数内联函数 #includeusing namespace std;inline double CirArea(double radius) return 3.14*radius*radius;void main() double r1(1.0),r2(2); coutCirArea(r1)endl; coutCi

153、rArea(r1+r2+4)endl; C+语语言言程程序序设设计计教教程程第第4章章函函数数内联函数定义内联函数定义内联函数调用内联函数调用运行结果运行结果运行结果运行结果:12479001600 2021/6/4172C+语语言言程程序序设设计计教教程程第第4章章函函数数4.3 4.3 内联函数内联函数 注意:注意:如果如果仅在仅在声明函数原型时加上关键字声明函数原型时加上关键字inlineinline,并不能达到内并不能达到内联效果联效果。内内联联函函数数的的定定义义必必须须出出现现在在对对该该函函数数的的调调用用之之前前,因因为为编编译译器器在在对对函函数数调调用用语语句句进进行行替替

154、换换时时,必必须须事事先先知知道道替替换换该该语语句句的代码是什么。的代码是什么。 由由于于计计算算机机的的资资源源总总是是有有限限的的,使使用用内内联联函函数数虽虽然然节节省省了了程程序序运运行行的的时时间间开开销销,但但却却增增大大了了代代码码占占用用内内存存的的空空间间开开销销。因因此此在在具具体体编编程程时时应应仔仔细细地地权权衡衡时时间间开开销销与与空空间间开销之间的矛盾,以确定是否采用内联函数。开销之间的矛盾,以确定是否采用内联函数。 2021/6/4173例如:例如: C+语语言言程程序序设设计计教教程程第第4章章函函数数4.4 4.4 带默认形参值的函数带默认形参值的函数 in

155、t sub(int x=8,int y=3) return x-y;void main(void) sub(20,15); /传递给形参传递给形参x,y的值分别为的值分别为20和和15 sub(10); /传递给形参传递给形参x,y的值分别为的值分别为10和和3 sub(); /传递给形参传递给形参x,y的值分别为的值分别为8和和3 C+C+语语言言允允许许在在函函数数说说明明或或函函数数定定义义中中为为形形参参预预赋赋一一个个默默认认的的值值,这这样样的的函函数数就就叫叫做做带带有有默默认认形形参参值值的的函函数数。在在调调用用带带有有默默认认参参数数值值的的函函数数时时,若若为为相相应应形

156、形参参指指定定了了实实参参,则则形形参参将将使使用用实实参参的的值值;否否则则,形形参参相相使使用用其其默默认认值值。这就大大地方便了函数的使用。这就大大地方便了函数的使用。 2021/6/4174C+语语言言程程序序设设计计教教程程第第4章章函函数数4.4 4.4 带默认形参值的函数带默认形参值的函数intf(inta,floatb=5.0,charc=.,intd=10);/正确intf(inta=1,floatb=5.0,charc=.,intd);/错误,d未给值intf(inta=1,floatb,charc=.,intd=10);/错误,b未给值 (1)(1) 若函数具有多个形参,

157、则缺省形参值必须自自右右向向左左连连续续地地定定义义,并且在一个缺省形参值的右边不能有未指定缺省值的参数。这是由于C+语言在函数调用时参数是自右至左入栈这一约定所决定的。 例如: 假如有如下声明:int f(int a,float b=5.0,char c=., int d=10);采用如下调用形式是错误的:f(8, , ,4); /语法错误(2)(2) 在调用一个函数时,如果省省去去了某个实参,则直直到到最最右右端端的的实实参参都都要要省省去去(当然,与它们对应的形参都要有缺省值)。 例如: 2021/6/4175C+语语言言程程序序设设计计教教程程第第4章章函函数数4.4 4.4 带默认形

158、参值的函数带默认形参值的函数intsub(intx=8,inty=3);/缺省形参值在函数原型中给出voidmain(void)sub(20,15);/20-15sub(10);/10-3sub();/8-3intsub(intx,inty)/缺省形参值没有在函数定义时给出returnx-y;(3)(3) 缺省形参值的说明必须出现在函数调用之之前前。这就是说,如果存在函数原型,则形参的缺省值应在函数原型中指定;否则在函数定义中指定。另外,若函数原型中已给出了形参的缺省值,则在函数定义中不不得得重重复复指指定定,即使所指定的缺省值完全相同也不行。 例如: 2021/6/4176C+语语言言程程序

159、序设设计计教教程程第第4章章函函数数4.4 4.4 带默认形参值的函数带默认形参值的函数intf(inta,floatb,char,intd=10);intf(inta,floatb,charc=.,intd=10);/错误:企图再次定义缺省参数c和d(4)(4)在同一个作用域,一旦定义了缺省形参值,就不能再定义它。 例如: intf(inta=6,floatb=5.0,charc=.,intd=10);voidmain(void)intf(inta=3,floatb=2.0,charc=n,intd=20);coutf()endl;/f函数使用局部缺省参数值(5)(5) 如果几个函数说明出现

160、在不同的作用域内,则允许分别为它们提供不同的缺省形参值。 例如: 2021/6/4177C+语语言言程程序序设设计计教教程程第第4章章函函数数4.4 4.4 带默认形参值的函数带默认形参值的函数/d参数的缺省值是函数调用。intf(inta,floatb=5.0,charc=.,intd=sub(20,15); (6)(6) 对形参缺省值的指定可以是初始化表达式,甚至可以包含函数调用。 例如: intf(int,float=5.0,char=.,int=sub(20,15); (7)(7) 在函数原型给出了形参的缺省值时,形参名可以省略。 例如: 2021/6/4178C+语语言言程程序序设设

161、计计教教程程第第4章章函函数数4.5 4.5 函数重载函数重载 函数重载:函数重载:两两个个以以上上的的函函数数,取取相相同同的的函函数数名名,但但是是形形参参的的个个数数和和类类型型不不同同,编编译译器器根根据据实实参参和和形形参参的的类类型型及及个个数数的的最最佳佳匹配匹配,自动决定调用哪一个函数,自动决定调用哪一个函数。 形参类型不同形参类型不同int add(int x, int y);float add(float x, float y);形参个数不同形参个数不同int add(int x, int y);int add(int x, int y, int z);2021/6/417

162、9#includeusing namespace std;int add(int x,int y) cout(int, int)t; return x+y; double add(double x,double y) cout(double, double)t; return x+y; int add(int x,double y) cout(int, double)t; return int(x+y); C+语语言言程程序序设设计计教教程程第第4章章函函数数函数重载函数重载函数重载函数重载函数重载函数重载2021/6/4180double add(double x,int y) cout(d

163、ouble,int)t;returnx+y;void main()coutadd(9,8)endl;coutadd(9.1,8.1)endl;coutadd(9,8.1)endl;coutadd(9.1,8)endl;C+语语言言程程序序设设计计教教程程第第4章章函函数数函数重载函数重载运行结果运行结果运行结果运行结果:(int, int) 17(double,double) 17.2(int, double) 17(double, int) 17 .1重载函数的调用重载函数的调用2021/6/4181C+语语言言程程序序设设计计教教程程第第4章章函函数数4.5 4.5 函数重载函数重载/ /

164、 C+C+无无法法区区分分这这两两个个函函数数。因因为为在在没没有有确确定定函函数数调调用用是是对对哪哪一一个个重重载载的的函函数数之之前前,返回类型是不知道的。返回类型是不知道的。 int add(int i1,int i2); int add(int i1,int i2); float add(int f1,int f2); float add(int f1,int f2);F注意注意: :(1)(1) 各各个个重重载载函函数数的的返返回回类类型型可可以以相相同同,也也可可以以不不同同。但但如如果果函函数数名名相相同同、形形参参表表也也相相同同,仅仅仅仅是是返返回回类类型型不不同同,则则是

165、是非非法法的的。在在编编译译时时会会认认为为是是语语法法错错误。误。 /将将charchar型转换成型转换成intint型,然后与型,然后与add(int,int)add(int,int)绑定。绑定。 add(A,A+0); add(A,A+0);/函数实参向函数实参向(double,double)(double,double)转换,然后与转换,然后与add(double,double)add(double,double)绑定。绑定。 add(float(8),float(9); add(float(8),float(9);/实参类型为实参类型为(long double, int),(long

166、 double, int),向低类型转化。向低类型转化。 add(long double(8),9); add(long double(8),9); (2)(2) 确确定定对对重重载载函函数数的的哪哪个个函函数数进进行行调调用用的的过过程程称称为为绑绑定定(binding)(binding), , 绑绑定定的的优优先先次次序序为为精精确确匹匹配配、对对实实参参的的类类型型向向高高类类型型转转换换后后的的匹匹配配、实实参参类类型型向向低低类类型型及相容类型转换后的匹配。及相容类型转换后的匹配。2021/6/4182C+语语言言程程序序设设计计教教程程第第4章章函函数数4.5 4.5 函数重载函数

167、重载 消除这种二义性的办法消除这种二义性的办法有:有: 添添加加重重载载函函数数定定义义,使使调调用用获获得得精精确确匹匹配配。如如:增增加加定定义义add(long double,int)add(long double,int) 将函数的实参进行强制类型的转换,使调用获得精确匹配。将函数的实参进行强制类型的转换,使调用获得精确匹配。例如:例如: 调用形式可改为调用形式可改为add(double(long double(8),9)add(double(long double(8),9),但改为,但改为add(long double(8),long double(9)add(long doubl

168、e(8),long double(9)同样出现绑定二义性。同样出现绑定二义性。绑定(匹配)二义性绑定(匹配)二义性 两个重载函数,编译器不知道进行哪种类型的转换,两个重载函数,编译器不知道进行哪种类型的转换,与哪个函数绑定与哪个函数绑定,这,这种现象就叫种现象就叫绑定(匹配)二义性绑定(匹配)二义性。F注意注意: :重载函数与带默认形参值的函数一起使用时,有可能引起二义性重载函数与带默认形参值的函数一起使用时,有可能引起二义性。例如:void add(int x, int y, int z=0); 当调用add(8,9)时,不知与add(int,int) 还是add(int,int,int=0

169、)绑定。消除这种二义性的办法是增加或减少实参个数。 2021/6/4183C+语语言言程程序序设设计计教教程程第第4章章函函数数4.6 4.6 函数模板函数模板 template 返回类型 函数名 (形参表) 函数体; 函数模板:函数模板: 可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。函数模板的定义形式为:函数模板的定义形式为: 模板参数表F意义:意义: 对于功能完全一样,只是参数类型不同函数,能写一段通用代码适用于多种不同的数据类型,会使代码的可重用性大大提高,从而提高软件的开发效率提高软件的开发效率。 2021/6/4184C+语语言言程程序序设设计

170、计教教程程第第4章章函函数数4.6 4.6 函数模板函数模板/将add函数定义成了一个函数模板:templateTadd(Tx,Ty)returnx+y;例如: F注意注意: :template关键字表示声明的是模板。中是模板的参数表,可以有一项或多项,其中的类型名称为参数化类型参数化类型,是一种抽 象类型或可变类型。class是类型关键字,也可以用typenametypename作为关键字。函数返回值类型可以是普通类型,也可以是模板参数表中指定的类型。模板参数表中的参数类型可以是普通类型。 2021/6/4185C+语语言言程程序序设设计计教教程程第第4章章函函数数4.6 4.6 函数模板函

171、数模板说明:说明: 根据中给出的具体类型,用类似于函数调用实参与形参结合的方式,将模板参数表中的参数化类型一一一一实实例例化化成具体的类型, 函数中的参数化类型也一一实例化。 如果模板参数表中有形式参数,还需要用常量表达式常量表达式去初始化。例如: 使用add(8, 9)将T add(T x, T y) 实例化成: double add(double, double) 使用sum 将T sum() 实例化成: int sum(), size获得初值100; 函函数数模模板板定义后,就可以用它生成各种具体的函数(称为模模板板函函数数)。在函数调用时,用函数模板生成模板函数实际上就是将模板参数表中

172、的参数化类型根据实参实例化(具体化)成具体类型。这个过程称为模模板板的的实实例例化化。函数模板实例化分为显式实例化显式实例化与隐式实例化隐式实例化。 (1)(1) 显式实例化显式实例化 函数名 (实参表)2021/6/4186C+语语言言程程序序设设计计教教程程第第4章章函函数数4.6 4.6 函数模板函数模板例如: 使用add( A,B) 将T add(T x, T y) 实例化成: char add(char, char)(2)(2) 隐式实例化隐式实例化: 隐式实例化的格式为函数调用式,实例化过程是在实参与形参结合时,用实参的类型实例化形参对应的参数化类型。 F注意注意: : 使用隐式实

173、例化无法初始化模板参数表中的普通类型的形参普通类型的形参,如果模板参数表中使用普通类型参数,必须使用显式初始化显式初始化。2021/6/41874.6 4.6 函数模板函数模板/*p4_8.cpp*函数模板*/#includeusingnamespacestd;template T1 add(T1 x, T2 y)cout(sizeof(T1),sizeof(T2)t;returnx+y;void main()coutadd(9,8)endl;coutadd(9.0,8.0)endl;coutadd(9,8.0)endl;coutadd(9.0,8)endl;coutadd(A,A-0)end

174、l;coutadd(longdouble(8),9)endl;123456789101112131415161718192021C+语语言言程程序序设设计计教教程程第第4章章函函数数函数模板定义函数模板定义模板函数调用模板函数调用运行结果运行结果运行结果运行结果:(4, 4) 17(8, 8) 17(4, 8) 17(8, 4) 17(1, 4) R(8, 4) 17 2021/6/4188C+语语言言程程序序设设计计教教程程第第4章章函函数数4.7 C+4.7 C+系统函数系统函数 C+不仅允许我们根据自己的需要定义函数,C+系统为我们提供了大量的标准库函数,这些函数原型在相应的头文件中,使

175、用时要包含相应的头文件。 C+C+函数分类表函数分类表 分别求x的正弦值、余弦值、正切值;x为弧度数doublesin(doublex)doublecos(doublex)doubletan(doublex)lnx即logexlog10xdoublelog(doublex)doublelog10(doublex)x的y次幂e的x次幂double pow(double x, doubley)doubleexp(doublex)分别求整型数、长整型、浮点数的绝对值intabs(inti)longlabs(longn)doublefabs(doublex)math.hcmath求x的平方根doubl

176、esqrt(doublex)数学C C式头文件式头文件C+C+头文件头文件功能简述功能简述 原型原型 类别类别 2021/6/4189C+语语言言程程序序设设计计教教程程第第4章章函函数数C C式头文件式头文件C+C+头文件头文件功能简述功能简述 原型原型 类别类别 将整数v按x进制转成字符串schar*itoa(intv,char*s,intx)time.hctime返回1970/1/1零点到目前的秒数time_ttime(time_t*timer)时间设 置 随 机 数 的 种 子产生0-RAND_MAX的随机数rand(unsignedseed)intrand()stdlib.hiost

177、ream将字符串转化成整数intatoi(char*s)类型转换memory.hiostream将s指向的内存区域的c个字节拷贝到d指向的区域void*memcpy(void*d,void*s,intc)内存操作unsignedstrlen(char*str)unsignedstrlen(char*str)其它字符串字符stdlib.hiostream终止正在执行的程序 exit(int)string.hiostreamchar *strcpy(char *s1, char*s2)char*strcpy(char*s1,char*s2)将c转换成小写、大写字母inttolower(intc),

178、inttoupper(intc)ctype.hiostreamc是否是字母,c是否是数字intisalpha(intc),intisdigit(intc)math.hcmath分别求x的反正弦值、反余弦值、反正切值doubleasin(doublex)doubleacos(doublex)doubleatan(doublex)数学F注意注意: :在C+中,旧式的C风格的头文件去掉了后缀.h,加上了前缀C,如stdlib.h在C+中变成了Cstdlib。当使用了:#include usingnamespacestd;时,许多头文件不需要包含了。在上面的表中,用iostream表示不再需要包含相应

179、的C+风格的头文件。4.7 C+4.7 C+系统函数系统函数 2021/6/41904.7 C+4.7 C+系统函数系统函数/*p4_9.cpp*利用系统函数rand()随机产生学生成绩*/#includeusingnamespacestd;void main()intx,i(0);srand(124);/设置种子dox=rand();if(x=5&x=1000)x=(x/5)*5;coutx/10.0t;i+;while(i100);123456789101112131415161718192021C+语语言言程程序序设设计计教教程程第第4章章函函数数随机函数随机函数【例【例4-94-9】产

180、生】产生100100个学生的某门功课的成绩,要求精确到个学生的某门功课的成绩,要求精确到0.50.5分。分。 解释解释解释解释:第10行设置随机数种子,使用rand()产生随机数时,以种子为基准,种子相同,每次产生的随机数也相同。2021/6/41914.8 本章小结本章小结 函数是一个功能独立的具有名称的程序代码。在程序的其他地方通过使用函数名与传递参数对函数进行调用。 一个函数只有先被声明或定义后,才能被调用。函数声明语句与函数定义中的函数头基本相同,所不同的是:声明语句必须以分号结束,形参表中可以为任意形参名或者不给出形参名。 函数调用过程包括通过栈内存保存返回地址传递参数、执行函数体、

181、返回三个阶段。将实参的值传递给形参的这种传值调用方式不改变实参的值。 递归函数适用于以递归方式定义的概念。 带inline关键字定义的函数为内联函数,在编译时将函数体展开到所有调用 处。内联函数的好处是节省函数调用过程的开销。 函数名相同,但对应形参表不同的一组函数称为重载函数。参数表不同是指参数个数不同或在个数相同的情况下至少有一个参数对应类型不同。 确定对重载函数中函数进行绑定的优先次序为精确匹配、对实参的类型向高类型转换后的匹配、实参类型向低类型及相容类型转换后的匹配。 对重载函数绑定时可能产生二义性,重载函数与带默认形参值的函数一起使用时,有可能引起二义性。 当既存在重载函数,又有函数

182、模板,优先绑定重载函数,只有不能精确匹配重载函数时,才实例化类模板。 内联函数的展开、重载函数的绑定、类模板的实例化与绑定均在编译时进行。 C+语语言言程程序序设设计计教教程程第第4章章函函数数2021/6/4192第四章第四章 类与对象类与对象C+语言程序设计主讲主讲 鲁莹鲁莹2021/6/4193C+语言程序设计西南林学院 鲁莹本章主要内容本章主要内容l面向对象的思想面向对象的思想lOOP的基本特点的基本特点l类概念和声明类概念和声明l对象对象l构造函数构造函数l析构函数析构函数l内联成员函数内联成员函数l拷贝构造函数拷贝构造函数l类的组合类的组合2021/6/4194C+语言程序设计西南

183、林学院 鲁莹回顾:面向过程的设计方法回顾:面向过程的设计方法重点重点:如何实现细节过程,将数据与函数分开。形式:形式:主模块+若干个子模块(main()+子函数)。特点:特点:自顶向下,逐步求精功能分解。缺点:缺点:效率低,程序的可重用性差。面向对象的思想2021/6/4195C+语言程序设计西南林学院 鲁莹面向对象的方法面向对象的方法观点:观点:自然界是由实体(对象)所组成。程序设计方法:程序设计方法:使用面向对象的观点来描述模仿并处理现实问题。要求:要求:高度概括、分类、和抽象。面向对象的思想2021/6/4196C+语言程序设计西南林学院 鲁莹抽象抽象抽象是对具体对象(问题)进行概括,抽

184、象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的抽出这一类对象的公共性质并加以描述的过程。过程。抽象的作用是表示同一类事物的本质。抽象的作用是表示同一类事物的本质。数据抽象数据抽象:描述某类对象的属性或状:描述某类对象的属性或状态。态。代码抽象代码抽象:描述某类对象的共有的行:描述某类对象的共有的行为特征或具有的功能。为特征或具有的功能。抽象的实现:通过类的声明。抽象的实现:通过类的声明。OOP的基本特点2021/6/4197C+语言程序设计西南林学院 鲁莹抽象实例抽象实例钟表钟表数据抽象:数据抽象:intHour,intMinute,intSecond代码抽象:代码抽象:

185、SetTime(),ShowTime()OOP的基本特点2021/6/4198C+语言程序设计西南林学院 鲁莹抽象实例抽象实例钟表类钟表类classClockpublic:voidSetTime(intNewH,intNewM,intNewS);voidShowTime();private:intHour,Minute,Second;OOP的基本特点2021/6/4199C+语言程序设计西南林学院 鲁莹类与对象类与对象类是对象的抽象;类是对象的抽象;对象是类的具体实例(对象是类的具体实例(instance););先声明一个类类型,在用它定义对象;先声明一个类类型,在用它定义对象;结构(结构(s

186、truct)是一个对象的类)是一个对象的类与与struct区别:区别:class中成员默认为私有;struct中成员默认为公有。2021/6/4200C+语言程序设计西南林学院 鲁莹抽象实例抽象实例人人数据抽象:数据抽象:char*name,char*gender,intage,intid代码抽象:代码抽象:生物属性角度:GetCloth(),Eat(),Step(),社会属性角度:Work(),Promote(),OOP的基本特点2021/6/4201C+语言程序设计西南林学院 鲁莹封装封装将抽象出的数据成员、代码成员相结将抽象出的数据成员、代码成员相结合,将它们视为一个整体。合,将它们视为

187、一个整体。目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员。实现封装:类声明中的OOP的基本特点2021/6/4202C+语言程序设计西南林学院 鲁莹封装封装实例:实例:classClockpublic:voidSetTime(intNewH,intNewM,intNewS);voidShowTime();private:intHour,Minute,Second;边界特定的访问权限OOP的基本特点外部接口2021/6/4203C+语言程序设计西南林学院 鲁莹继承与派生继承与派生是是C+中支持层次分类的一种机制,中支持层次分类的一

188、种机制,允许程序员在保持原有类特性的基础上,允许程序员在保持原有类特性的基础上,进行更具体的说明。进行更具体的说明。实现:声明派生类实现:声明派生类OOP的基本特点2021/6/4204C+语言程序设计西南林学院 鲁莹多态性多态性多态:同一名称,不同的功能实现方式。多态:同一名称,不同的功能实现方式。目的:达到行为标识统一,减少程序中标目的:达到行为标识统一,减少程序中标识符的个数。识符的个数。实现:重载函数和虚函数实现:重载函数和虚函数OOP的基本特点2021/6/4205C+语言程序设计西南林学院 鲁莹c+中的类中的类类是具有相同属性和行为的一组对象类是具有相同属性和行为的一组对象的集合,

189、是一个数据结构。的集合,是一个数据结构。类为属于该类的全部对象提供了统一类为属于该类的全部对象提供了统一的抽象描述,其内部包括属性和行为的抽象描述,其内部包括属性和行为两个主要部分。两个主要部分。利用类可以实现数据的封装、隐藏、利用类可以实现数据的封装、隐藏、继承与派生。继承与派生。利用类易于编写大型复杂程序,其模利用类易于编写大型复杂程序,其模块化程度比块化程度比C中采用函数更高。中采用函数更高。类和对象2021/6/4206C+语言程序设计西南林学院 鲁莹类的声明形式类的声明形式 类是一种用户自定义类型,声明形式:类是一种用户自定义类型,声明形式:class类名称public:公有成员(外

190、部接口)private:私有成员protected:保护型成员;类和对象2021/6/4207C+语言程序设计西南林学院 鲁莹“类定义类定义”说明:说明:class:定义类的关键字。:定义类的关键字。类名称:标识一个类的标识符。类名称:标识一个类的标识符。一对大括号内是类的说明部分,说明该类的一对大括号内是类的说明部分,说明该类的所有成员。所有成员。类的成员包含数据成员和成员函数。类的成员包含数据成员和成员函数。类的成员从访问权限上分为三类:公有类的成员从访问权限上分为三类:公有public,私有,私有private,和保护,和保护protected。默认为私有。默认为私有。类和对象2021/

191、6/4208C+语言程序设计西南林学院 鲁莹类的访问权限类的访问权限公有类型成员公有类型成员public在关键字在关键字public后面声明,它们是类与外后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类部的接口,任何外部函数都可以访问公有类型数据和函数。型数据和函数。类和对象2021/6/4209C+语言程序设计西南林学院 鲁莹类的访问权限类的访问权限私有类型成员私有类型成员private在关键字在关键字private后面声明,只允许本类中后面声明,只允许本类中的函数及其友元类的函数访问,而类外部的的函数及其友元类的函数访问,而类外部的任何函数都不能访问。任何函数都不能访问。如果紧

192、跟在类名称的后面声明私有成员,则关键如果紧跟在类名称的后面声明私有成员,则关键字字privateprivate可以省略。可以省略。类和对象2021/6/4210C+语言程序设计西南林学院 鲁莹类的访问权限类的访问权限保护类型保护类型protected与与private类似,其差别表现在继承与派生时类似,其差别表现在继承与派生时对派生类的影响不同。对派生类的影响不同。除了允许本类中的函数及其友元类的函数访除了允许本类中的函数及其友元类的函数访问外,该类的派生类的成员也可以访问。问外,该类的派生类的成员也可以访问。类和对象2021/6/4211C+语言程序设计西南林学院 鲁莹class Sampl

193、e int i;protected:int j;public:int k;int geti() return i;/类的成员函数可以访问类的私有类的成员函数可以访问类的私有成员成员 int getj() return j;/类的成员函数可以访问类的保护类的成员函数可以访问类的保护成员成员 int getk() return k;/类的成员函数可以访问类的公共类的成员函数可以访问类的公共有成员有成员;Sample a;/定义定义Sample类的对象类的对象aa.i;/非法非法a.j;/非法非法a.k;/合法合法2021/6/4212C+语言程序设计西南林学院 鲁莹类的访问权限类的访问权限公有成员

194、是类的对外表现,而私有成员和保护成员是公有成员是类的对外表现,而私有成员和保护成员是类的内部实现。类的内部实现。类的成员可以访问类的所有成员;类的成员可以访问类的所有成员;类的对象对类的成员的访问受限制。类的对象对类的成员的访问受限制。划分访问权限的优点:划分访问权限的优点:1、信息隐蔽。即将类的内部实现和外部表现分开;、信息隐蔽。即将类的内部实现和外部表现分开;2、数据保护。即将类的重要信息保护起来,以免其他程序、数据保护。即将类的重要信息保护起来,以免其他程序不恰当地修改。不恰当地修改。2021/6/4213C+语言程序设计西南林学院 鲁莹类的成员类的成员classClockpublic:

195、voidSetTime(intNewH,intNewM,intNewS);voidShowTime();private:intHour,Minute,Second;类和对象成员数据成员函数2021/6/4214C+语言程序设计西南林学院 鲁莹成员数据成员数据与一般的变量声明相同,但需要将它与一般的变量声明相同,但需要将它放在类的声明体中。放在类的声明体中。类和对象2021/6/4215void Clock : SetTime(int NewH, int NewM, int NewS) Hour=NewH; Minute=NewM; Second=NewS;void Clock : ShowTi

196、me() coutHour:Minute:Second;19类的成员函数类的成员函数2021/6/4216C+语言程序设计西南林学院 鲁莹可在类的定义体中定义,也可在定义体外定义。可在类的定义体中定义,也可在定义体外定义。在类定义体外定义成员函数,需加上类域标记在类定义体外定义成员函数,需加上类域标记(类名(类名:) 。在类定义体中实现的函数称为在类定义体中实现的函数称为“内联函数内联函数”。在类定义体外实现的函数可在函数说明和定义在类定义体外实现的函数可在函数说明和定义出分别加上出分别加上“inline”表示表示“内联函数内联函数”。类的成员函数类的成员函数2021/6/4217C+语言程序

197、设计西南林学院 鲁莹内联成员函数举例内联成员函数举例(一一)class Point public: void Init(int initX,int initY) X=initX; Y=initY; int GetX() return X; int GetY() return Y; private: int X,Y;类和对象2021/6/4218C+语言程序设计西南林学院 鲁莹内联成员函数举例内联成员函数举例(二二)class Point public: void Init(int initX,int initY); int GetX(); int GetY(); private: int X,

198、Y; inline void Point: Init(int initX,int initY) X=initX; Y=initY; 类和对象2021/6/4219inline void Point: Init(int initX,int initY) X=initX; Y=initY;inline int Point:GetX() return X;inline int Point:GetY() return Y;252021/6/4220C+语言程序设计西南林学院 鲁莹对象对象类的对象是该类的某一特定实体,即类的对象是该类的某一特定实体,即类类型的变量。类类型的变量。在定义类时,系统不会给类

199、分配存储在定义类时,系统不会给类分配存储空间,只有定义类对象时才会给对象空间,只有定义类对象时才会给对象分配相应的内存空间。分配相应的内存空间。声明形式:声明形式: 类名类名 对象名;对象名;例:例: Clock myClock;类和对象2021/6/4221C+语言程序设计西南林学院 鲁莹类中成员的访问方式类中成员的访问方式类中成员互访类中成员互访直接使用成员名类外访问类外访问使用“对象名.成员名”方式访问public属性的成员类和对象2021/6/4222C+语言程序设计西南林学院 鲁莹class Sample int i;protected:int j;public:int k;int

200、geti() return i;/类的成员函数可以访问类的私有类的成员函数可以访问类的私有成员成员 int getj() return j;/类的成员函数可以访问类的保护类的成员函数可以访问类的保护成员成员 int getk() return k;/类的成员函数可以访问类的公共类的成员函数可以访问类的公共有成员有成员;Sample a;/定义定义Sample类的对象类的对象aa.i;/非法非法a.j;/非法非法a.k;/合法合法2021/6/4223C+语言程序设计西南林学院 鲁莹例例4-1类的应用举例类的应用举例#includeusing namespace std;class Clock

201、./类的声明略类的声明略/.类的实现略类的实现略void main(void) Clock myClock; myClock.SetTime(8,30,30); myClock.ShowTime();类和对象2021/6/4224C+语言程序设计西南林学院 鲁莹构造函数和析构函数构造函数和析构函数在定义一个对象的同时,希望能给它的数在定义一个对象的同时,希望能给它的数据成员赋初值,即对象的初始化。据成员赋初值,即对象的初始化。在特定对象使用结束时,需要做一些清理在特定对象使用结束时,需要做一些清理工作。工作。初始化工作和清理工作分别由两个特殊的初始化工作和清理工作分别由两个特殊的成员函数完成:

202、构造函数和析构函数成员函数完成:构造函数和析构函数2021/6/4225C+语言程序设计西南林学院 鲁莹构造函数(构造函数(Constructor)构造函数的作用是用于对象的初始化。构造函数的作用是用于对象的初始化。构造函数是构造函数是与类同名,没有返回值,在对象创建与类同名,没有返回值,在对象创建时时由系统自动调用的函数。由系统自动调用的函数。如果程序中未声明,则系统自动产生出一个如果程序中未声明,则系统自动产生出一个默认默认形式形式的隐含的构造函数。这个构造函数的函数体的隐含的构造函数。这个构造函数的函数体是空的,因此默认形式的构造函数不具备任何功是空的,因此默认形式的构造函数不具备任何功

203、能。能。允许为允许为内联内联函数、函数、重载重载函数、函数、带默认形参值带默认形参值的函的函数数构造函数和析构函数2021/6/4226C+语言程序设计西南林学院 鲁莹构造函数举例构造函数举例class Clockpublic:Clock (int NewH, int NewM, int NewS);/构造函数构造函数void SetTime(int NewH, int NewM, int NewS);void ShowTime();private:int Hour,Minute,Second;构造函数和析构函数2021/6/4227构造函数的实现:构造函数的实现:Clock:Clock(in

204、t NewH, int NewM, int NewS)Hour= NewH;Minute= NewM;Second= NewS;建立对象时构造函数的作用:建立对象时构造函数的作用:void main() Clock c (0,0,0); /隐含调用构造函数,将初始值作为实参。隐含调用构造函数,将初始值作为实参。 c.ShowTime();312021/6/4228C+语言程序设计西南林学院 鲁莹拷贝构造函数拷贝构造函数拷贝构造函数是一种特殊的构造函数,其形参为拷贝构造函数是一种特殊的构造函数,其形参为本类的对象引用。本类的对象引用。class类名public:类名(形参);/构造函数类名(类名

205、&对象名);/拷贝构造函数的说明.;类名:类名(类名&对象名)/拷贝构造函数的实现函数体构造函数和析构函数2021/6/4229C+语言程序设计西南林学院 鲁莹拷贝构造函数拷贝构造函数当用类的一个对象去初始化该类的另一个当用类的一个对象去初始化该类的另一个对象时系统自动调用拷贝构造函数实现拷对象时系统自动调用拷贝构造函数实现拷贝赋值。贝赋值。只能有一个参数,并且是对某个对象的引只能有一个参数,并且是对某个对象的引用。用。每个类必须有一个拷贝初始化函数每个类必须有一个拷贝初始化函数,如果如果没有说明没有说明,编译系统自动生成一个具有上编译系统自动生成一个具有上述形式的默认拷贝初始化构造函数述形式

206、的默认拷贝初始化构造函数.构造函数和析构函数2021/6/4230C+语言程序设计西南林学院 鲁莹析构函数析构函数完成对象被删除前的一些清理工作。完成对象被删除前的一些清理工作。在对象的生存期结束的时刻系统自动在对象的生存期结束的时刻系统自动调用它,然后再释放此对象所属的空调用它,然后再释放此对象所属的空间。间。如果程序中未声明析构函数,编译器如果程序中未声明析构函数,编译器将自动产生一个默认的析构函数。将自动产生一个默认的析构函数。构造函数和析构函数2021/6/4231C+语言程序设计西南林学院 鲁莹析构函数析构函数析构函数名字为符号析构函数名字为符号”加类名加类名.析构函数没有参数和返回

207、值。析构函数没有参数和返回值。一个类中只可能定义一个析构函数,一个类中只可能定义一个析构函数,所以析构函数不能重载。所以析构函数不能重载。构造函数和析构函数2021/6/4232C+语言程序设计西南林学院 鲁莹析构函数析构函数对于一般对象,系统会自动释放并且对于一般对象,系统会自动释放并且启动调用析构函数。启动调用析构函数。对于用对于用new创建的指针对象,必须在创建的指针对象,必须在使用使用delete运算符释放时,才调用析运算符释放时,才调用析构函数。构函数。构造函数和析构函数2021/6/4233C+语言程序设计西南林学院 鲁莹类的应用举例类的应用举例(例例4-3)一圆型游泳池如图所示,

208、现在需在其周围建一圆型游泳池如图所示,现在需在其周围建一圆型过道,并在其四周围上栅栏。栅栏价格为一圆型过道,并在其四周围上栅栏。栅栏价格为35元元/米,过道造价为米,过道造价为20元元/平方米。过道宽度为平方米。过道宽度为3米,游泳池半径由键盘输入。要求编程计算并米,游泳池半径由键盘输入。要求编程计算并输出过道和栅栏的造价。输出过道和栅栏的造价。游泳池过道2021/6/4234C+语言程序设计西南林学院 鲁莹实验内容:实验内容:1、定定义义一一个个类类Score,它它含含有有私私有有数数据据成成员员english_score( 英英 语语 分分 数数 ) 、 公公 有有 成成 员员 函函 数数

209、 setscore( )和和printscore( ),其其中中setscore( )用用来来设设置置english_score的的值值,print-score( )用用来来输输出出english_score的的值值。在在主主程程序序中中定定义义类类score的的普普通通对对象象stu1和和指指针针对对象象stu2,其其英英语语成成绩绩分别为分别为85.5和和93.5 ,输出这两个分数。,输出这两个分数。2、在在第第1题题的的基基础础上上,模模仿仿上上课课所所讲讲例例题题,加加入入构构造造函函数数,拷拷贝贝初初始始化化构构造造函函数数,析析构构函函数数进进行练习。行练习。3、定定义义一一个个三

210、三角角形形类类Ctriangel,求求三三角角形形的的面面积和周长积和周长(加入重载和异常处理加入重载和异常处理);2021/6/4235第五章第五章 C+程序的结构程序的结构鲁莹鲁莹C+语言程序设计2021/6/4236C+语言程序设计西南林学院 鲁莹本章主要内容本章主要内容l作用域与可见性作用域与可见性l对象的生存期对象的生存期l类的静态成员类的静态成员l友元友元l常类型常类型l编译预处理命令编译预处理命令l多文件结构和工程多文件结构和工程2021/6/4237C+语言程序设计西南林学院 鲁莹函数原形的作用域函数原形的作用域l函数原型声明时中行参的作用域始于函数原型声明时中行参的作用域始于

211、(,结束于,结束于)。l例如,设有下列原型声明:例如,设有下列原型声明:doubleArea(doubleradius);radius 的作用域仅在于此,的作用域仅在于此,不能用于程序正文其它地方,不能用于程序正文其它地方,因而函数原型中形参标识符因而函数原型中形参标识符可有可无。可有可无。作用域与可见性2021/6/4238C+语言程序设计西南林学院 鲁莹块作用域块作用域l在块中声明的标识符,其作用域自声明处起,限在块中声明的标识符,其作用域自声明处起,限于块中,例如:于块中,例如:void fun(int a) int b(a); if (b0) int c; . l函数的形参与函数体属于

212、一个块。函数的形参与函数体属于一个块。c的作用域b的作用域作用域与可见性2021/6/4239C+语言程序设计西南林学院 鲁莹类作用域类作用域l类作用域作用于特定的成员名。类作用域作用于特定的成员名。l类类X的成员的成员M具有类作用域具有类作用域,对对M的访问方式的访问方式如下:如下: 如果在X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以访问成员M。通过表达式x.M或者X:M访问。通过表达式prt-M作用域与可见性2021/6/4240C+语言程序设计西南林学院 鲁莹文件作用域文件作用域l不在前述各个作用域中出现的声明,不在前述各个作用域中出现的声明,具有文件作用域,这样声明

213、的标识符具有文件作用域,这样声明的标识符的作用域开始于声明点,结束于文件的作用域开始于声明点,结束于文件尾。尾。l函数、全局变量和常量具有文件作用函数、全局变量和常量具有文件作用域。域。作用域与可见性2021/6/4241C+语言程序设计西南林学院 鲁莹可见性可见性l可见性是从对标识符的引用的角度来谈的概念。可见性是从对标识符的引用的角度来谈的概念。l程序运行到某一处,能够引用到的标识符称为程序运行到某一处,能够引用到的标识符称为该处可见的标识符。该处可见的标识符。l可见性表示从内层作用域向外层作用域可见性表示从内层作用域向外层作用域“看看”时时能看见什么。能看见什么。l如果标识在某处可见,则

214、就可以在该处引用此如果标识在某处可见,则就可以在该处引用此标识符。标识符。块作用域类作用域文件作用域作用域与可见性2021/6/4242C+语言程序设计西南林学院 鲁莹可见性可见性l标识符应声明在先,引用在后。标识符应声明在先,引用在后。l如果某个标识符在外层中声明,且在内层中如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则该标识符在内层没有同一标识符的声明,则该标识符在内层可见。可见。l对于两个嵌套的作用域,如果在内层作用域对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标识符,则内声明了与外层作用域中同名的标识符,则外层作用域的标识符在内层不可见。外层作用域

215、的标识符在内层不可见。作用域与可见性2021/6/4243C+语言程序设计西南林学院 鲁莹1.#include2.usingnamespacestd;3.inti;/全局变量,文件作用域4.voidmain()5.6.i=5;/文件作用域的i赋初值7./子块18.inti;/局部变量,块作用域9.i=7;10.couti=iendl;/输出711.12.couti=iendl;/输出513.作用域与可见性例例 5.12021/6/4244C+语言程序设计西南林学院 鲁莹对象的生存期对象的生存期对象从产生到结束的这段时间就是对象从产生到结束的这段时间就是它的生存期。它的生存期。在对象生存期内,对

216、象将在对象生存期内,对象将保持它的值,直到被更新为止。保持它的值,直到被更新为止。2021/6/4245C+语言程序设计西南林学院 鲁莹静态生存期静态生存期l指一旦为其分配了存储单元,则在整指一旦为其分配了存储单元,则在整个程序执行期间,它们将固定地占有个程序执行期间,它们将固定地占有分配给它们的存储单元。分配给它们的存储单元。l这种生存期与程序的运行期相同。这种生存期与程序的运行期相同。l在文件作用域中声明的对象具有这种在文件作用域中声明的对象具有这种生存期。生存期。l在函数内部声明静态生存期对象,要在函数内部声明静态生存期对象,要冠以关键字冠以关键字static 。对象的生存期2021/6

217、/4246C+语言程序设计西南林学院 鲁莹#includeusingnamespacestd;inti=5;/文件作用域intmain()couti=iendl;return0;i具有静态生存期对象的生存期例例2021/6/4247C+语言程序设计西南林学院 鲁莹动态生存期动态生存期l程序运行期间动态分配存储空间。程序运行期间动态分配存储空间。l块作用域中声明的,没有用块作用域中声明的,没有用static修是的对修是的对象是动态生存期的对象(习惯称局部生存象是动态生存期的对象(习惯称局部生存期对象)。期对象)。l开始于程序执行到声明点时,结束于命名开始于程序执行到声明点时,结束于命名该标识符的

218、作用域结束处。该标识符的作用域结束处。对象的生存期2021/6/4248C+语言程序设计西南林学院 鲁莹#includeusingnamespacestd;voidfun();voidmain()fun();fun();voidfun()staticinta=1;inti=5;a+;i+;couti=i,a=aendl;运行结果:i=6,a=2i=6,a=3i是动态生存期a是静态生存期对象的生存期例例2021/6/4249C+语言程序设计西南林学院 鲁莹例例5-2 变量的生存期与可见性变量的生存期与可见性#includeusing namespace std;int i=1; / i 为全局变

219、量,具有静态生存期。为全局变量,具有静态生存期。void main(void) static int a; / 静态局部变量,有全局寿命,局部可见。静态局部变量,有全局寿命,局部可见。 int b=-10; / b, c为局部变量,具有动态生存期。为局部变量,具有动态生存期。 int c=0; void other(void); cout-MAIN-n; cout i: i a: a b: b c: cendl; c=c+8; other(); cout-MAIN-n; cout i: i a: a b: b c: cendl; i=i+10; other(); 对象的生存期2021/6/42

220、50void other(void) static int a=2; static int b; / a,b为静态局部变量,具有全局寿命,局部可见。为静态局部变量,具有全局寿命,局部可见。 /只第一次进入函数时被初始化。只第一次进入函数时被初始化。 int c=10; / C为局部变量,具有动态生存期,为局部变量,具有动态生存期, /每次进入函数时都初始化。每次进入函数时都初始化。 a=a+2; i=i+32; c=c+5; cout-OTHER-n; cout i: i a: a b: b c: cendl; b=a;172021/6/4251运行结果:运行结果:-MAIN- i: 1 a:

221、 0 b: -10 c: 0-OTHER- i: 33 a: 4 b: 0 c: 15-MAIN- i: 33 a: 0 b: -10 c: 8-OTHER- i: 75 a: 6 b: 4 c: 15182021/6/4252C+语言程序设计西南林学院 鲁莹例例5-3具有静态、动态生存期对象的时钟程序具有静态、动态生存期对象的时钟程序#includeusing namespace std;class Clock /时钟类声明时钟类声明public:/外部接口外部接口Clock();void SetTime(int NewH, int NewM, int NewS); /三个形参均具有函数原型

222、作用域三个形参均具有函数原型作用域void ShowTime();Clock()private:/私有数据成员私有数据成员int Hour,Minute,Second;对象的生存期2021/6/4253/时钟类成员函数实现时钟类成员函数实现Clock:Clock()/构造函数构造函数 Hour=0;Minute=0;Second=0;void Clock:SetTime(int NewH, int NewM, int NewS) Hour=NewH;Minute=NewM;Second=NewS;void Clock:ShowTime() coutHour:Minute:Secondendl;

223、202021/6/4254Clock globClock;/声明对象声明对象globClock, /具有静态生存期,文件作用域具有静态生存期,文件作用域void main() /主函数主函数coutFirst time output:endl;/引用具有文件作用域的对象:引用具有文件作用域的对象:globClock.ShowTime(); /对象的成员函数具有类作用域对象的成员函数具有类作用域globClock.SetTime(8,30,30);Clock myClock(globClock); /声明具有块作用域的对象声明具有块作用域的对象myClockcoutSecond time out

224、put:endl;myClock.ShowTime(); /引用具有块作用域的对象引用具有块作用域的对象212021/6/4255程序的运行结果为:程序的运行结果为:First time output:0:0:0Second time output:8:30:30222021/6/4256C+语言程序设计西南林学院 鲁莹类的静态成员类的静态成员l类的静态成员包括:类的静态成员包括:静态数据成员静态数据成员静态成员函数静态成员函数l提出类的静态成员目的:提出类的静态成员目的:数据共享数据共享2021/6/4257C+语言程序设计西南林学院 鲁莹类的静态数据成员类的静态数据成员l静态数据成员是类中

225、所有对象共享的成员,而不是某个对象的成员。l对静态数据成员的操作和一般数据成员一样,定义为私有的静态数据成员不能由外界访问。l因为静态数据成员不从属于任何一个具体对象,所以必须对它初始化,而且初始化不能在构造函数中进行。2021/6/4258C+语言程序设计西南林学院 鲁莹类的静态数据成员的使用类的静态数据成员的使用l静态数据成员的定义与一般数据成员相静态数据成员的定义与一般数据成员相似,但前面要加上似,但前面要加上static关键字。关键字。l静态数据成员的初始化格式:静态数据成员的初始化格式::=l引用静态数据成员的格式:引用静态数据成员的格式::2021/6/4259C+语言程序设计西南

226、林学院 鲁莹类的静态成员函数类的静态成员函数l静态成员函数的定义:static 一般函数定义一般函数定义l调用静态成员函数的格式:调用静态成员函数的格式::();l静态成员函数只能访问静态数据成员、静态成静态成员函数只能访问静态数据成员、静态成员函数和类以外的函数和数据,不能访问类中员函数和类以外的函数和数据,不能访问类中的非静态数据成员(因为非静态数据成员只有的非静态数据成员(因为非静态数据成员只有对象存在时才有意义。)。对象存在时才有意义。)。2021/6/4260C+语言程序设计西南林学院 鲁莹友元友元l在程序设计中,将数据与操作数据的行为进行在程序设计中,将数据与操作数据的行为进行有机

227、地结合,这就是封装。有机地结合,这就是封装。lC+语言提供类来实现封装,类是属性和操作语言提供类来实现封装,类是属性和操作的结合体,并且在定义类的属性和操作时,规的结合体,并且在定义类的属性和操作时,规定了它们的可见性。定了它们的可见性。l通过封装将部分成员作为类与外部的接口,而通过封装将部分成员作为类与外部的接口,而将其它的成员隐藏起来,以防外界的干扰和误将其它的成员隐藏起来,以防外界的干扰和误操作,使程序的不同模块之间的相互影响减小操作,使程序的不同模块之间的相互影响减小到最低限度。到最低限度。友元2021/6/4261C+语言程序设计西南林学院 鲁莹友元友元l在类中,一般将数据成员定义为

228、私有成员,在类中,一般将数据成员定义为私有成员,并通过公有成员访问函数对外提供的界面。并通过公有成员访问函数对外提供的界面。l友元是友元是C+提供的一种破坏数据封装和数提供的一种破坏数据封装和数据隐藏的机制。据隐藏的机制。l友元(友元(friend)函数:不是类的一部分,)函数:不是类的一部分,但又需要频繁地访问类的所有成员。但又需要频繁地访问类的所有成员。l友元:友元函数和友元类。友元:友元函数和友元类。l友元提高程序的运行效率,但也牺牲了类友元提高程序的运行效率,但也牺牲了类的封装型。的封装型。友元2021/6/4262C+语言程序设计西南林学院 鲁莹友元函数友元函数l定义:定义:frie

229、nd ();l友元函数说明的位置可在类的任何部位,既友元函数说明的位置可在类的任何部位,既可以在可以在public区,也可以在区,也可以在protected区,区,意义完全一样。意义完全一样。l友元函数定义则在类的外部,一般与类的成友元函数定义则在类的外部,一般与类的成员函数定义放在一起。员函数定义放在一起。友元2021/6/4263C+语言程序设计西南林学院 鲁莹例例5-6 使用友元函数计算两点距离使用友元函数计算两点距离#include #include using namespace std;class Point /Point类声明类声明 public:/外部接口外部接口Point(i

230、nt xx=0, int yy=0) X=xx;Y=yy;int GetX() return X;int GetY() return Y;friend float Distance(Point &a, Point &b); private:/私有数据成员私有数据成员int X,Y;友元2021/6/4264double Distance( Point& a, Point& b) double dx=a.X-b.X; double dy=a.Y-b.Y; return sqrt(dx*dx+dy*dy);int main() Point p1(3.0, 5.0), p2(4.0, 6.0); d

231、ouble d=Distance(p1, p2); coutThe distance is dendl; return 0;362021/6/4265C+语言程序设计西南林学院 鲁莹友元类友元类l若一个类为另一个类的友元,则此类若一个类为另一个类的友元,则此类的所有成员函数都是类的所有成员函数都是类B的友元函数。的友元函数。l声明语法:将友元类名在另一个类中声明语法:将友元类名在另一个类中使用使用friend修饰说明。修饰说明。友元2021/6/4266C+语言程序设计西南林学院 鲁莹友元类举例友元类举例class A friend class B;/B是是A的友元类的友元类 public:

232、void Display() coutxendl; private: int x;class B public: void Set(int i); void Display(); private: A a;友元2021/6/4267void B:Set(int i) a.x=i;void B:Display() a.Display();392021/6/4268C+语言程序设计西南林学院 鲁莹友元关系是单向的友元关系是单向的如果声明如果声明B类是类是A类的友元,类的友元,B类的类的成员函数就可以访问成员函数就可以访问A类的私有和保护类的私有和保护数据,但数据,但A类的成员函数却不能访问类的成员

233、函数却不能访问B类的私有、保护数据。类的私有、保护数据。2021/6/4269C+语言程序设计西南林学院 鲁莹友元关系不能传递友元关系不能传递B类是类是A类的友元,类的友元,C类是类是B类的友类的友元,元,C类和类和A类之间,如果没有声明,类之间,如果没有声明,就没有任何友元关系,不能进行数据共就没有任何友元关系,不能进行数据共享。享。2021/6/4270C+语言程序设计西南林学院 鲁莹常类型常类型l常类型:用常类型:用const说明的类型说明的类型l常类型的变量或对象的值是不能改变的,常类型的变量或对象的值是不能改变的,所以能够达到既保证数据共享又防止改所以能够达到既保证数据共享又防止改变

234、数据的目的。变数据的目的。2021/6/4271C+语言程序设计西南林学院 鲁莹常引用常引用l常引用:被引用的对象不能被更新。常引用:被引用的对象不能被更新。const&;例如:constint&n;其中,n是一个常引用,它所引用的对象不会被更新。l常对象:常对象:必须进行初始化必须进行初始化, ,不能被更新。不能被更新。类名const对象名2021/6/4272C+语言程序设计西南林学院 鲁莹常对象常对象l常对象:常对象:指对象常量指对象常量l定义常对象是必须进行初始化,且不能定义常对象是必须进行初始化,且不能被更新。被更新。const2021/6/4273C+语言程序设计西南林学院 鲁莹常

235、对象成员常对象成员l包括常成员函数和常数据成员包括常成员函数和常数据成员l常成员函数常成员函数使用const关键字说明的函数。常成员函数不更新对象的数据成员,也不能调用该类中没有用const修饰的成员函数。常成员函数说明格式:()const;如果将一个对象说明为常对象,则通过该类对象只能调用它的常成员函数而不能调用其他成员函数。const关键字可以被用于参与对重载函数的区分2021/6/4274C+语言程序设计西南林学院 鲁莹常数据成员常数据成员l如同一般数据一样,类的成员数据可以是常量如同一般数据一样,类的成员数据可以是常量和常引用。和常引用。l如果在一个类中说明了常数据成员,那么构造如果在

236、一个类中说明了常数据成员,那么构造函数就只能通过初始化列表对该数据成员进行函数就只能通过初始化列表对该数据成员进行初始化。初始化。2021/6/4275C+语言程序设计西南林学院 鲁莹编译预处理命令编译预处理命令l#include 包含指令包含指令将一个源文件嵌入到当前源文件中该点处。#includel按标准方式搜索,文件位于C+系统目录的include子目录下#include文件名l首先在当前目录中搜索,若没有,再按标准方式搜索。l#define 宏定义指令宏定义指令定义符号常量,很多情况下已被const定义语句取代。定义带参数宏,已被内联函数取代。l#undef删除由#define定义的宏

237、,使之不再起作用。2021/6/4276C+语言程序设计西南林学院 鲁莹条件编译指令条件编译指令 #if #if 和和 #endif #endif条件编译:条件编译:一般情况,程序中的所有语句都参加编译,一般情况,程序中的所有语句都参加编译,但有时也希望根据一定的条件去编译文但有时也希望根据一定的条件去编译文件的不同部分。件的不同部分。#ifdef /当当“ 标识符标识符”非零时编译非零时编译 #endif.编译预处理命令2021/6/4277C+语言程序设计西南林学院 鲁莹条件编译指令条件编译指令#else#else #ifdef /当当“ 标识符标识符”非零时编译非零时编译#else/当“

238、标识符”为零时编译#endif编译预处理命令2021/6/4278C+语言程序设计西南林学院 鲁莹条件编译指令条件编译指令 #elif#ifdef /当当“ 标识符标识符”非零时编译非零时编译#elif /当当“ 标识符标识符”非零时编译非零时编译#else /其它情况下编译其它情况下编译#endif编译预处理命令2021/6/4279C+语言程序设计西南林学院 鲁莹条件编译指令条件编译指令#ifdef 标识符标识符 程序段程序段1#else 程序段程序段2#endif如果如果“标识符标识符”经经#defined定义过,且未定义过,且未经经undef删除,则编译程序段删除,则编译程序段1,否则

239、编,否则编译程序段译程序段2。编译预处理命令2021/6/4280C+语言程序设计西南林学院 鲁莹条件编译指令条件编译指令#ifndef #else #endif如果如果“标识符标识符”未被定义过,则编译程序未被定义过,则编译程序段段1,否则编译程序段,否则编译程序段2。编译预处理命令2021/6/4281C+语言程序设计西南林学院 鲁莹多文件结构(例多文件结构(例5-10)l一个源程序可以划分为多个源文件:一个源程序可以划分为多个源文件:类声明文件(.h文件)类实现文件(.cpp文件)类的使用文件(main()所在的.cpp文件)l利用工程来组合各个文件。利用工程来组合各个文件。2021/6

240、/4282C+语言程序设计西南林学院 鲁莹不使用条件编译的头文件不使用条件编译的头文件/main.cpp#include file1.h#include file2.hvoid main() /file1.h#include head.h /file2.h#include head.h /head.h class Point 多文件结构2021/6/4283C+语言程序设计西南林学院 鲁莹使用条件编译的头文件使用条件编译的头文件/head.h#ifndef HEAD_H #define HEAD_H class Point #endif多文件结构2021/6/4284C+语言程序设计西南林学院

241、 鲁莹实验内容实验内容l编写一个程序,设计一个类,用于统计一个办的学编写一个程序,设计一个类,用于统计一个办的学生成绩,其中使用一个静态数据成员生成绩,其中使用一个静态数据成员sumfs存储总存储总分和一个静态成员函数分和一个静态成员函数rusmfs()返回该总分。返回该总分。l编写一个程序采用友元函数求一个点到直线的距离。编写一个程序采用友元函数求一个点到直线的距离。l设计一个函数模板设计一个函数模板max求一个数组中的最大的求一个数组中的最大的元素,并以整数数组和字符数组进行调用。元素,并以整数数组和字符数组进行调用。l在上题的基础上进行改进,设计一个类模板在上题的基础上进行改进,设计一个

242、类模板Max,求一个数组中的最大的元素,并以整数,求一个数组中的最大的元素,并以整数数组和字符数组进行调用。数组和字符数组进行调用。2021/6/4285第六章第六章 数组数组 指针与字符串指针与字符串鲁莹鲁莹C+语言程序设计2021/6/4286C+语言程序设计清华大学 郑莉本章主要内容本章主要内容l数组数组l指针指针l动态存储分配动态存储分配l指针与数组指针与数组l指针与函数指针与函数l字符串字符串2021/6/4287C+语言程序设计清华大学 郑莉数组的概念数组的概念数组数组是具有一定是具有一定顺序关系顺序关系的若干的若干相相同类型变量的集合体同类型变量的集合体,组成数组的变量,组成数组

243、的变量称为该数组的称为该数组的元素元素。数组属于构造类型。数组属于构造类型。数组2021/6/4288C+语言程序设计清华大学 郑莉一维数组的声明与引用一维数组的声明与引用l一维数组的声明一维数组的声明类型说明符数组名常量表达式;例如:inta10;表示a为整型数组,有10个元素:a0.a9l引用引用必须先声明,后使用。只能逐个引用数组元素,而不能一次引用整个数组例如:a0=a5+a7-a2*3数组名的构成方法与一般变量名相同。数组2021/6/4289C+语言程序设计清华大学 郑莉例例6. 1一维数组的声明与引用一维数组的声明与引用#include using namespace std;v

244、oid main() int A10,B10;int i;for(i=0;i10;i+)Ai=i*2-1;B10-i-1=Ai;数组 for(i=0;i10;i+) coutAi =Ai; cout Bi = Biendl;2021/6/4290C+语言程序设计清华大学 郑莉一维数组的存储顺序一维数组的存储顺序数组元素在内存中顺次存放,它们的地址是连续的。例如:具有10个元素的数组a,在内存中的存放次序如下:数组名字是数组首元素的内存地址。数组名是一个常量,不能被赋值。a0 a1a2 a3 a4a5 a6 a7a8 a9a数组2021/6/4291C+语言程序设计清华大学 郑莉一维数组的初始化

245、一维数组的初始化可以在编译阶段使数组得到初值:可以在编译阶段使数组得到初值:在声明数组时对数组元素赋以初值。例如:staticinta10=0,1,2,3,4,5,6,7,8,9;可以只给一部分元素赋初值。例如:staticinta10=0,1,2,3,4;在对全部数组元素赋初值时,可以不指定数组长度。例如:staticinta=1,2,3,4,5数组2021/6/4292C+语言程序设计清华大学 郑莉#includeusing namespace std;void main() int i; static int f20=1,1; /初始化第初始化第0、1个数个数 for(i=2;i20;i

246、+) fi=fi-2+fi-1; /求第求第219个数个数 for(i=0;i20;i+) /输出,每行输出,每行5个数个数/ if(i%5=0) coutendl; cout.width(12); /设置输出宽度为设置输出宽度为12 coutfi; 例:用数组来处理求例:用数组来处理求Fibonacci数列问题数列问题2021/6/4293C+语言程序设计清华大学 郑莉例:用数组来处理求例:用数组来处理求Fibonacci数列问题数列问题2021/6/4294C+语言程序设计清华大学 郑莉一维数组应用举例一维数组应用举例循环从键盘读入若干组选择题答案,循环从键盘读入若干组选择题答案,计算并输

247、出每组答案的正确率,直到输计算并输出每组答案的正确率,直到输入入ctrl+z为止。为止。每组连续输入每组连续输入5个答案,每个答案个答案,每个答案可以是可以是a.d。数组2021/6/4295#include using namespace std;void main(void) char key = a,c,b,a,d;char c;int ques = 0, numques = 5, numcorrect = 0;cout Enter the numques question tests: endl; while (cin.get(c) if (c != n)if (c = keyques

248、) numcorrect+; cout ;elsecout *; else cout Score float(numcorrect)/numques*100 %; ques = 0; / reset variables numcorrect = 0; cout endl; continue; ques+;2962021/6/4296运行结果:运行结果:acbba * Score 60%acbad Score 100%abbda * * Score 40%bdcba* Score 0%2972021/6/4297C+语言程序设计清华大学 郑莉二维数组的声明及引用二维数组的声明及引用数据类型数据类

249、型 标识符标识符常量表达式常量表达式1常量表达式常量表达式2 ;例例: int a53;表示a为整型二维数组,其中第一维有5个 下 标 ( 04) , 第 二 维 有 3个 下 标(02),数组的元素个数为15,可以用于存放5行3列的整型数据表格。数组2021/6/4298C+语言程序设计清华大学 郑莉l存储顺序存储顺序按行存放,上例中数组a的存储顺序为:l二维数组的声明二维数组的声明类型说明符数组名常量表达式常量表达式例如:floata34;a00a01a02a03a10a11a12a13a20a21a22a23a0a00a01a02a03a1a10a11a12a13a2a20a21a22a

250、23a可以理解为:l引用引用例如:b12=a23/2下标不要越界下标不要越界下标不要越界下标不要越界二维数组的声明及引用二维数组的声明及引用数组2992021/6/4299C+语言程序设计清华大学 郑莉l将所有数据写在一个将所有数据写在一个内,按顺序赋值内,按顺序赋值例如:staticinta34=1,2,3,4,5,6,7,8,9,10,11,12;l分行给二维数组赋初值分行给二维数组赋初值例如:staticinta34=1,2,3,4,5,6,7,8,9,10,11,12;l可以对部分元素赋初值可以对部分元素赋初值例如:staticinta34=1,0,6,0,0,11;二维数组的初始化二

251、维数组的初始化数组3002021/6/4300C+语言程序设计清华大学 郑莉数组作为函数参数数组作为函数参数l数组元素作实参,与单个变量一样。数组元素作实参,与单个变量一样。l数组名作参数,形、实参数都应是数数组名作参数,形、实参数都应是数组名,类型要一样,传送的是数组首组名,类型要一样,传送的是数组首地址。对形参数组的改变会直接影响地址。对形参数组的改变会直接影响到实参数组。到实参数组。数组2021/6/4301C+语言程序设计清华大学 郑莉例例6-2 使用数组名作为函数参数使用数组名作为函数参数l主函数中初始化一个矩阵并将每个元主函数中初始化一个矩阵并将每个元素都输出,然后调用子函数,分别

252、计素都输出,然后调用子函数,分别计算每一行的元素之和,将和直接存放算每一行的元素之和,将和直接存放在每行的第一个元素中,返回主函数在每行的第一个元素中,返回主函数之后输出各行元素的和。之后输出各行元素的和。数组2021/6/4302#include using namespace std;void RowSum(int A4, int nrow) int sum;for (int i = 0; i nrow; i+)sum = 0;for(int j = 0; j 4; j+)sum += Aij;cout Sum of row i is sum endl; Ai0=sum; 3032021/

253、6/4303void main(void) int Table34 = 1,2,3,4,2,3,4,5,3,4,5,6;for (int i = 0; i 3; i+)for (int j = 0; j 4; j+)cout Tableij ;cout endl;RowSum(Table,3); for (int i = 0; i 3; i+) cout Tablei03042021/6/4304运行结果:运行结果:1 2 3 42 3 4 53 4 5 6Sum of row 0 is 10Sum of row 1 is 14Sum of row 2 is 1810 14 183052021

254、/6/4305C+语言程序设计清华大学 郑莉对象数组对象数组l声明:声明:类名数组名元素个数;l访问方法:访问方法:通过下标访问数组名下标.成员名数组2021/6/4306C+语言程序设计清华大学 郑莉对象数组初始化对象数组初始化l数组中每一个元素对象被创建时,系统数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。都会调用类构造函数初始化该对象。l通过初始化列表赋值。通过初始化列表赋值。例:PointA2=Point(1,2),Point(3,4);l如果没有为数组元素指定显式初始值,如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化(调用默数组元素便使用默认值初始化

255、(调用默认构造函数)。认构造函数)。数组2021/6/4307C+语言程序设计清华大学 郑莉数组元素所属类的构造函数数组元素所属类的构造函数l不声明构造函数,则采用默认构造函数。不声明构造函数,则采用默认构造函数。l各元素对象的初值要求为相同的值时,各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。可以声明具有默认形参值的构造函数。l各元素对象的初值要求为不同的值时,各元素对象的初值要求为不同的值时,需要声明带形参的构造函数。需要声明带形参的构造函数。l当数组中每一个对象被删除时,系统都当数组中每一个对象被删除时,系统都要调用一次析构函数。要调用一次析构函数。数组2021/6

256、/4308C+语言程序设计清华大学 郑莉例例6-3 对象数组应用举例对象数组应用举例/Point.h#if !defined(_POINT_H)#define _POINT_Hclass Point public: Point(); Point(int xx,int yy); Point(); void Move(int x,int y); int GetX() return X; int GetY() return Y; private: int X,Y;#endif数组2021/6/4309/6-2.cpp#includeusing namespace std;#include Point

257、.hPoint:Point() X=Y=0; coutDefault Constructor called.endl;Point:Point(int xx,int yy) X=xx; Y=yy; cout Constructor called.endl;Point :Point() coutDestructor called.endl; void Point :Move(int x,int y) X=x; Y=y; 3102021/6/4310#include#include Point.husing namespace std;int main() coutEntering main.end

258、l; Point A2; for(int i=0;i2;i+) Ai.Move(i+10,i+20); coutExiting main.endl; return 0;3112021/6/4311运行结果:运行结果:Entering main.Default Constructor called.Default Constructor called.Exiting main.Destructor called.Destructor called.3122021/6/4312C+语言程序设计清华大学 郑莉关于内存地址关于内存地址l内存空间的访问方式内存空间的访问方式通过变量名访问通过地址访问l地

259、址运算符:地址运算符:&例:intvar;则&var表示变量var在内存中的起始地址2021/6/4313C+语言程序设计清华大学 郑莉声明例:staticinti;staticint*i_pointer=&i;指向整型变量的指针概念指针:指针:内存地址,用于间接访问内存单元指针变量:指针变量:用于存放地址的变量20003i_pointer*i_pointeri2000内存用户数据区变量i变量j变量i_pointer362000200020043010引用例1:i=3;例2:*i_pointer=3;指针2021/6/4314C+语言程序设计清华大学 郑莉l语法形式存储类型数据类型*指针名初始

260、地址;例:int*pa=&a;l注意事项用变量地址作为初值时,该变量必须在指针初始化之前已说明过,且变量类型应与指针类型一致。可以用一个已赋初值的指针去初始化另一个指针变量。不要用一个内部auto变量去初始化static指针。指针2021/6/4315C+语言程序设计清华大学 郑莉指针变量的赋值运算指针变量的赋值运算指针名指针名=地址地址l“地址地址”中存放的数据类型与指针类型必须中存放的数据类型与指针类型必须相符。相符。l向指针变量赋的值必须是地址常量或变量,向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数不能是普通整数。但可以赋值为整数0,表,表示空指针。示空指针。l

261、指针的类型是它所指向变量的类型,而不指针的类型是它所指向变量的类型,而不是指针本身数据值的类型,任何一个指针是指针本身数据值的类型,任何一个指针本身的数据值都是本身的数据值都是unsigned long int型。型。l允许声明指向允许声明指向 void 类型的指针。该指针可类型的指针。该指针可以被赋予任何类型对象的地址。以被赋予任何类型对象的地址。例:例: void *general; 指针2021/6/4316C+语言程序设计清华大学 郑莉例例6-5 指针的声明、赋值与使用指针的声明、赋值与使用#includeusing namespace std;void main() int *i_p

262、ointer;/声明声明int型指针型指针i_pointerint i;/声明声明int型数型数ii_pointer=&i;/取取i的地址赋给的地址赋给i_pointeri=10;/int型数赋初值型数赋初值coutOutput int i=iendl; /输出输出int型数的值型数的值coutOutput int pointer i=*i_pointerendl; /输出输出int型指针所指地址的内容型指针所指地址的内容指针2021/6/4317程序运行的结果是:程序运行的结果是:Output int i=10Output int pointer i=103182021/6/4318C+语言

263、程序设计清华大学 郑莉例例6-6 void类型指针的使用类型指针的使用void vobject; /错,不能声明错,不能声明void类型的变量类型的变量void *pv; /对,可以声明对,可以声明void类型的指针类型的指针int *pint; int i;void main() /void类型的函数没有返回值类型的函数没有返回值pv = &i; /void类型指针指向整型变量类型指针指向整型变量 / void指针赋值给指针赋值给int指针需要类型强制转换指针需要类型强制转换: pint = (int *)pv; 指针2021/6/4319C+语言程序设计清华大学 郑莉指向常量的指针指向常量

264、的指针l不能通过指针来改变所指对象的值,但指针本不能通过指针来改变所指对象的值,但指针本身可以改变,可以指向另外的对象身可以改变,可以指向另外的对象。l例例1char*name1=John;/name1是一般指针*name1=A;/编译正确,运行出错l例例2constchar*name1=John;/指向常量的指针chars=abc;name1=s;/正确,name1本身的值可以改变*name1=1;/编译时指出错误指针2021/6/4320C+语言程序设计清华大学 郑莉指针类型的常量指针类型的常量l若声明指针常量,则指针本身的值不能若声明指针常量,则指针本身的值不能被改变。例:被改变。例:c

265、har*constname2=John;name2=abc;/错误,指针常量值不能改变2021/6/4321C+语言程序设计清华大学 郑莉指针变量的算术运算指针变量的算术运算l指针与整数的加减运算指针与整数的加减运算指针p加上或减去n,其意义是指针当前指向位置的前方或后方第n个数据的地址。这种运算的结果值取决于指针指向的数据类型。l指针加一,减一运算指针加一,减一运算指向下一个或前一个数据。例如:y=*px+相当于y=*(px+)(*和+优先级相同,自右向左运算)指针2021/6/4322papa-2pa-1pa+1pa+2pa+3*(pa-2)*pa*(pa+1)*(pa+2)*(pa+3)

266、*(pa-1)short*pa3232021/6/4323pb-1pbpb+1pb+2*(pb-1)*pb*(pb+1)*(pb+2)long*pb3242021/6/4324C+语言程序设计清华大学 郑莉l关系运算关系运算指向相同类型数据的指针之间可以进行各种关系运算。指向不同数据类型的指针,以及指针与一般整数变量之间的关系运算是无意义的。指针可以和零之间进行等于或不等于的关系运算。例如:p=0或p!=0l赋值运算赋值运算向指针变量赋的值必须是地址常量或变量,不能是普通整数。但可以赋值为整数0,表示空指针。指针2021/6/4325C+语言程序设计清华大学 郑莉指向数组元素的指针指向数组元素

267、的指针l声明与赋值声明与赋值例:inta10,*pa;pa=&a0;或pa=a;l通过指针引用数组元素通过指针引用数组元素经过上述声明及赋值后:*pa就是a0,*(pa+1)就是a1,.,*(pa+i)就是ai.ai,*(pa+i),*(a+i),pai都是等效的。不能写a+,因为a是数组首地址是常量。指针2021/6/4326C+语言程序设计清华大学 郑莉例例6-7设有一个设有一个int型数组型数组a,有,有10个元素。用个元素。用三种方法输出各元素:三种方法输出各元素:使用数组名和下标使用数组名和指针运算使用指针变量指针2021/6/4327main() int a10; int i; f

268、or(i=0; iai; coutendl; for(i=0; i10; i+) coutai;使用数组名和下标使用数组名和下标3282021/6/4328main() int a10; int i; for(i=0; iai; coutendl; for(i=0; i10; i+) cout*(a+i);使用数组名指针运算使用数组名指针运算2021/6/4329使用指针变量使用指针变量main() int a10; int *p,i; for(i=0; iai; coutendl; for(p=a; p(a+10); p+) cout*p;2021/6/4330C+语言程序设计清华大学 郑莉

269、指针数组指针数组l数组的元素是指针型数组的元素是指针型l例:例:Point *pa2; 由由pa0,pa1两个指针组成两个指针组成指针2021/6/4331C+语言程序设计清华大学 郑莉例例6-8 利用指针数组存放单位矩阵利用指针数组存放单位矩阵#include using namespace std;void main() int line1=1,0,0; /声明数组,矩阵的第一行声明数组,矩阵的第一行int line2=0,1,0; /声明数组,矩阵的第二行声明数组,矩阵的第二行int line3=0,0,1; /声明数组,矩阵的第三行声明数组,矩阵的第三行int *p_line3;/声明

270、整型指针数组声明整型指针数组p_line0=line1; /初始化指针数组元素初始化指针数组元素p_line1=line2;p_line2=line3;指针2021/6/4332/输出单位矩阵输出单位矩阵 coutMatrix test:endl;for(int i=0;i3;i+)/对指针数组元素循环对指针数组元素循环 for(int j=0;j3;j+)/对矩阵每一行循环对矩阵每一行循环 coutp_lineij ; coutendl;输出结果为:输出结果为:Matrix test:Matrix test:1,0,01,0,00,1,00,1,00,0,10,0,13332021/6/43

271、33C+语言程序设计清华大学 郑莉例例6-9 二维数组举例二维数组举例#include using namespace std;void main() int array223=11,12,13,21,22,23; for(int i=0;i2;i+) cout*(array2+i)endl; for(int j=0;j3;j+) cout*(*(array2+i)+j) ; /或者或者 coutarray2ij ; coutendl;指针2021/6/4334在某次运行之后,程序的输出结果为:在某次运行之后,程序的输出结果为:0X0065FDE011,12,130X0065FDEC21,22

272、,233352021/6/4335C+语言程序设计清华大学 郑莉以指针作为函数参数以指针作为函数参数l以地址方式传递数据,可以用来返回以地址方式传递数据,可以用来返回函数处理结果。函数处理结果。l实参是数组名时形参可以是指针。实参是数组名时形参可以是指针。指针与函数2021/6/4336C+语言程序设计清华大学 郑莉例例6.10题目:读入三个浮点数,将整数部分和题目:读入三个浮点数,将整数部分和小数部分分别输出小数部分分别输出#include using namespace std;void splitfloat(float x, int *intpart, float *fracpart)

273、/形参形参intpart、 fracpart是指针是指针 *intpart = int(x);/ 取取x的整数部分的整数部分 *fracpart = x - *intpart; /取取x的小数部分的小数部分指针与函数2021/6/4337void main(void)int i, n;float x, f;cout Enter three (3) floating point numbers endl;for (i = 0; i x;splitfloat(x,&n,&f); /变量地址做实参变量地址做实参cout Integer Part is n Fraction Part is f end

274、l;3382021/6/4338运行结果:运行结果:Enter three (3) floating point numbers 4.7Integer Part is 4 Fraction Part is 0.78.913Integer Part is 8 Fraction Part is 0.913-4.7518Integer Part is -4 Fraction Part is -0.75183392021/6/4339C+语言程序设计清华大学 郑莉例例: 输出数组元素的内容和地址输出数组元素的内容和地址#include #include using namespace std;void

275、 Array_Ptr(long *P, int n) int i;cout In func, address of array is unsigned long(P) endl;cout Accessing array in the function using pointers endl;for (i = 0; i n; i+)cout Address for index i is unsigned long(P+i);cout Value is *(P+i) endl;指针与函数2021/6/4340void main(void)long list5 = 50, 60, 70, 80, 9

276、0; cout In main, address of array is unsigned long(list) endl;cout endl; Array_Ptr(list,5);2021/6/4341运行结果:运行结果:In main, address of array is 6684132In func, address of array is 6684132Accessing array in the function using pointers Address for index 0 is 6684132 Value is 50 Address for index 1 is 668

277、4136 Value is 60 Address for index 2 is 6684140 Value is 70 Address for index 3 is 6684144 Value is 80 Address for index 4 is 6684148 Value is 903422021/6/4342C+语言程序设计清华大学 郑莉指向常量的指针做形参指向常量的指针做形参#includeusing namespace std;const int N=6;void print(const int *p,int n);void main() int arrayN; for(int i

278、=0;iarrayi; print(array,N);指针2021/6/4343void print(const int *p, int n) cout*p; for(int i=1;in;i+) cout.*(p+i); coutendl;3442021/6/4344C+语言程序设计清华大学 郑莉当函数的返回值是地址时,该当函数的返回值是地址时,该函数就是指针形函数。函数就是指针形函数。声明形式声明形式 存储类型存储类型 数据类型数据类型 *函数名函数名()指针与函数2021/6/4345C+语言程序设计清华大学 郑莉l声明形式声明形式 存储类型存储类型 数据类型数据类型 (*函数指针名函数

279、指针名)(); l含义:含义:数据指针指向数据存储区,而函数指针指向的是程序代码存储区。指向函数的指针指向函数的指针指针与函数2021/6/4346C+语言程序设计清华大学 郑莉例例6-11函数指针函数指针#include using namespace std;void print_stuff(float data_to_ignore);void print_message(float list_this_data);void print_float(float data_to_print);void (*function_pointer)(float);void main()float p

280、i = (float)3.14159;float two_pi = (float)2.0 * pi;指针与函数2021/6/4347 print_stuff(pi); function_pointer = print_stuff; function_pointer(pi); function_pointer = print_message; function_pointer(two_pi); function_pointer(13.0); function_pointer = print_float; function_pointer(pi); print_float(pi);3482021/

281、6/4348void print_stuff(float data_to_ignore) coutThis is the print stuff function.n; void print_message(float list_this_data) coutThe data to be listed is list_this_dataendl; void print_float(float data_to_print) coutThe data to be printed is data_to_print成员名ptr-getx()相当于(*ptr).getx();指针2021/6/4351C

282、+语言程序设计清华大学 郑莉对象指针应用举例对象指针应用举例int main() Point A(5,10); Point *ptr; ptr=&A; int x; x=ptr-GetX(); coutxX=xx;this-Y=yy;指针2021/6/4356C+语言程序设计清华大学 郑莉指向类的非静态成员的指针指向类的非静态成员的指针l通过指向成员的指针只能访问公有成员通过指向成员的指针只能访问公有成员l声明指向成员的指针声明指向成员的指针声明指向公有数据成员的指针类型说明符类名:*指针名;声明指向公有函数成员的指针类型说明符(类名:*指针名)(参数表);指针2021/6/4357C+语言程

283、序设计清华大学 郑莉指向类的非静态成员的指针指向类的非静态成员的指针l指向数据成员的指针指向数据成员的指针说明指针应该指向哪个成员指针名=&类名:数据成员名;通过对象名(或对象指针)与成员指针结合来访问数据成员对象名.*类成员指针名或:对象指针名*类成员指针名指针2021/6/4358C+语言程序设计清华大学 郑莉指向类的非静态成员的指针指向类的非静态成员的指针l指向函数成员的指针指向函数成员的指针初始化指针名=类名:函数成员名;通过对象名(或对象指针)与成员指针结合来访问函数成员(对象名.*类成员指针名)(参数表)或:(对象指针名*类成员指针名)(参数表)指针2021/6/4359C+语言程

284、序设计清华大学 郑莉指向类的非静态成员的指针指向类的非静态成员的指针例例6-13 访问对象的公有成员函数的不同方式访问对象的公有成员函数的不同方式voidmain()/主函数 PointA(4,5);/声明对象APoint*p1=&A;/声明对象指针并初始化/声明成员函数指针并初始化int(Point:*p_GetX)()=Point:GetX;/(1)使用成员函数指针访问成员函数cout(A.*p_GetX)()endl;/(2)使用对象指针访问成员函数coutGetX)()endl;/(3)使用对象名访问成员函数coutA.GetX()endl;指针2021/6/4360C+语言程序设计清

285、华大学 郑莉指向类的静态成员的指针指向类的静态成员的指针l对类的静态成员的访问不依赖于对象对类的静态成员的访问不依赖于对象l可以用普通的指针来指向和访问静态可以用普通的指针来指向和访问静态成员成员l例例6-14通过指针访问类的静态数据成员l例例6-15通过指针访问类的静态函数成员指针2021/6/4361C+语言程序设计清华大学 郑莉例例6-14通过指针访问类的静态数据成员通过指针访问类的静态数据成员#include using namespace std;class Point/Point类声明类声明public:/外部接口外部接口Point(int xx=0, int yy=0) X=xx

286、;Y=yy;countP+;/构造函数构造函数Point(Point &p);/拷贝构造函数拷贝构造函数int GetX() return X;int GetY() return Y;static int countP;/静态数据成员引用性说明静态数据成员引用性说明private:/私有数据成员私有数据成员int X,Y;Point:Point(Point &p)X=p.X; Y=p.Y; countP+; int Point:countP=0;/静态数据成员定义性说明静态数据成员定义性说明指针2021/6/4362void main() /主函数主函数 /声明一个声明一个int型指针,指向类

287、的静态成员型指针,指向类的静态成员int *count=&Point:countP; Point A(4,5);/声明对象声明对象AcoutPoint A,A.GetX(),A.GetY(); /直接通过指针访问静态数据成员直接通过指针访问静态数据成员cout Object id=*countendl;Point B(A);/声明对象声明对象BcoutPoint B,B.GetX() ,B.GetY(); /直接通过指针访问静态数据成员直接通过指针访问静态数据成员cout Object id=*countendl; 3632021/6/4363C+语言程序设计清华大学 郑莉例例6-15通过指针

288、访问类的静态函数成员通过指针访问类的静态函数成员#include using namespace std;class Point/Point类声明类声明 public:/外部接口外部接口/其它函数略其它函数略static void GetC() /静态函数成员静态函数成员 cout Object id=countPendl; private:/私有数据成员私有数据成员int X,Y;static int countP;/静态数据成员引用性说明静态数据成员引用性说明;/ 函数实现略函数实现略int Point:countP=0;/静态数据成员定义性说明静态数据成员定义性说明指针2021/6/43

289、64void main() /主函数主函数 /指向函数的指针,指向类的静态成员函数指向函数的指针,指向类的静态成员函数void (*gc)()=Point:GetC;Point A(4,5);/声明对象声明对象AcoutPoint A,A.GetX(),A.GetY();gc(); /输出对象序号,通过指针访问静态函数成员输出对象序号,通过指针访问静态函数成员Point B(A);/声明对象声明对象BcoutPoint B,B.GetX(),B.GetY();gc(); /输出对象序号,通过指针访问静态函数成员输出对象序号,通过指针访问静态函数成员3652021/6/4365C+语言程序设计清

290、华大学 郑莉动态申请内存操作符动态申请内存操作符 newnew 类型名类型名T(初值列表)(初值列表)功能:功能:在程序执行期间,申请用于存放在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表类型对象的内存空间,并依初值列表赋以初值。赋以初值。结果值:结果值:成功:成功:T类型的指针,指向新类型的指针,指向新分配的内存。失败:分配的内存。失败:0(NULL)动态存储分配2021/6/4366C+语言程序设计清华大学 郑莉释放内存操作符释放内存操作符deletedelete 指针指针P功能:功能:释放指针释放指针P所指向的内存。所指向的内存。P必须必须是是new操作的返回值。操作的返

291、回值。动态存储分配2021/6/4367C+语言程序设计清华大学 郑莉例例6-16 动态创建对象举例动态创建对象举例#includeusing namespace std;class Point public: Point() X=Y=0; coutDefault Constructor called.n; Point(int xx,int yy) X=xx; Y=yy; cout Constructor called.n; Point() coutDestructor called.n; int GetX() return X; int GetY() return Y;void Move(i

292、nt x,int y) X=x; Y=y; private: int X,Y;动态存储分配2021/6/4368int main() coutStep One:endl; Point *Ptr1=new Point; delete Ptr1; coutStep Two:endl; Ptr1=new Point(1,2); delete Ptr1; return 0;运行结果:运行结果:Step One:Default Constructor called.Destructor called.Step Two:Constructor called.Destructor called.369202

293、1/6/4369C+语言程序设计清华大学 郑莉例例6-17动态创建对象数组举例动态创建对象数组举例#includeusing namespace std;class Point /类的声明同例类的声明同例6-16,略,略 ;int main() Point *Ptr=new Point2; /创建对象数组创建对象数组 Ptr0.Move(5,10); /通过指针访问数组元素的成员通过指针访问数组元素的成员 Ptr1.Move(15,20); /通过指针访问数组元素的成员通过指针访问数组元素的成员 coutDeleting.endl; delete Ptr; /删除整个对象数组删除整个对象数组

294、return 0;动态存储分配2021/6/4370运行结果:运行结果:Default Constructor called.Default Constructor called.Deleting.Destructor called.Destructor called.3712021/6/4371例例6-18动态数组类动态数组类#includeusing namespace std;class Point /类的声明同例类的声明同例6-16 ;class ArrayOfPoints public: ArrayOfPoints(int n) numberOfPoints=n; points=ne

295、w Pointn; ArrayOfPoints() coutDeleting.endl; numberOfPoints=0; delete points; Point& Element(int n) return pointsn; private: Point *points; int numberOfPoints;3722021/6/4372void main()int number;coutnumber; /创建对象数组创建对象数组 ArrayOfPoints points(number); /通过指针访问数组元素的成员通过指针访问数组元素的成员 points.Element(0).Mov

296、e(5,10); /通过指针访问数组元素的成员通过指针访问数组元素的成员 points.Element(1).Move(15,20); 3732021/6/4373运行结果如下:运行结果如下:Please enter the number of points:2Default Constructor called.Default Constructor called.Deleting.Destructor called.Destructor called.3742021/6/4374C+语言程序设计清华大学 郑莉动态创建多维数组动态创建多维数组new 类型名类型名T下标表达式下标表达式1下标表

297、达式下标表达式2;如果内存申请成功,如果内存申请成功,new运算返回一个指运算返回一个指向新分配内存首地址的指针,是一个向新分配内存首地址的指针,是一个T类型类型的数组,数组元素的个数为除最左边一维外的数组,数组元素的个数为除最左边一维外各维下标表达式的乘积。例如:各维下标表达式的乘积。例如:char (*fp)3;fp = new char23;2021/6/4375char(*fp)3;fpfp+1fp00fp01fp02fp10fp11fp123762021/6/4376C+语言程序设计清华大学 郑莉例例6-18动态创建多维数组动态创建多维数组#includeusing namespac

298、e std;void main() float (*cp)98;int i,j,k;cp = new float898;for (i=0; i8; i+)for (j=0; j9; j+)for (k=0; k9; k+) *(*(*(cp+i)+j)+k)=i*100+j*10+k; /通过指针访问数组元素通过指针访问数组元素动态存储分配2021/6/4377for (i=0; i8; i+)for (j=0; j9; j+) for (k=0; k8; k+) /将指针将指针cp作为数组名使用,作为数组名使用, /通过数组名和下标访问数组元素通过数组名和下标访问数组元素 coutcpijk

299、 ; coutendl;coutendl;3782021/6/4378C+语言程序设计清华大学 郑莉动态存储分配函数动态存储分配函数lvoid *malloc( size );参数参数size:欲分配的字节数:欲分配的字节数返回值:返回值: 成功,则返回成功,则返回void型指针。型指针。 失败,则返回空指针。失败,则返回空指针。头文件:头文件: 和和 动态存储分配2021/6/4379C+语言程序设计清华大学 郑莉动态内存释放函数动态内存释放函数lvoid free( void *memblock );参数参数memblock: 指针,指向需释放的指针,指向需释放的 内存。内存。返回值:无返

300、回值:无头文件:头文件: 和和 动态存储分配2021/6/4380C+语言程序设计清华大学 郑莉浅拷贝与深拷贝浅拷贝与深拷贝l浅拷贝浅拷贝实现对象间数据元素的一一对应复制。l深拷贝深拷贝当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指的对象进行复制。浅拷贝与深拷贝2021/6/4381C+语言程序设计清华大学 郑莉例例6-20对象的浅拷贝对象的浅拷贝#includeusing namespace std;class Point /类的声明同例类的声明同例6-16 /;class ArrayOfPoints /类的声明同例类的声明同例6-18 /;浅拷贝与深拷贝2021

301、/6/4382void main() int number;cinnumber; ArrayOfPoints pointsArray1(number); pointsArray1.Element(0).Move(5,10); pointsArray1.Element(1).Move(15,20); ArrayOfPoints pointsArray2(pointsArray1); coutCopy of pointsArray1:endl; coutPoint_0 of array2: pointsArray2.Element(0).GetX() , pointsArray2.Element(

302、0).GetY()endl; coutPoint_1 of array2: pointsArray2.Element(1).GetX() , pointsArray2.Element(1).GetY()endl;3832021/6/4383 pointsArray1.Element(0).Move(25,30); pointsArray1.Element(1).Move(35,40); coutAfter the moving of pointsArray1:endl; coutPoint_0 of array2: pointsArray2.Element(0).GetX() , points

303、Array2.Element(0).GetY()endl; coutPoint_1 of array2: pointsArray2.Element(1).GetX() , pointsArray2.Element(1).GetY()endl;3842021/6/4384运行结果如下:运行结果如下:Please enter the number of points:2Default Constructor called.Default Constructor called.Copy of pointsArray1:Point_0 of array2: 5, 10Point_1 of array2

304、: 15, 20After the moving of pointsArray1:Point_0 of array2: 25, 30Point_1 of array2: 35, 40Deleting.Destructor called.Destructor called.Deleting.接下来程序出现异常,也就是运行错误。接下来程序出现异常,也就是运行错误。3852021/6/4385拷贝前拷贝后pointsArray1的数组元素占用的内存pointsnumberOfPointspointsArray1pointsnumberOfPointspointsArray1pointsArray1的

305、数组元素占用的内存pointsnumberOfPointspointsArray23862021/6/4386C+语言程序设计清华大学 郑莉例例6-21对象的深拷贝对象的深拷贝#includeusing namespace std;class Point /类的声明同例类的声明同例6-16 ;class ArrayOfPoints public: ArrayOfPoints(ArrayOfPoints& pointsArray); /其它成员同例其它成员同例6-18 ;浅拷贝与深拷贝2021/6/4387ArrayOfPoints :ArrayOfPoints(ArrayOfPoints& p

306、ointsArray) numberOfPoints =pointsArray.numberOfPoints; points=new PointnumberOfPoints; for (int i=0; inumberOfPoints; i+) pointsi.Move(pointsArray.Element(i).GetX(), pointsArray.Element(i).GetY();void main() /同例同例6-20 3882021/6/4388程序的运行结果如下:程序的运行结果如下:Please enter the number of points:2Default Cons

307、tructor called.Default Constructor called.Default Constructor called.Default Constructor called.Copy of pointsArray1:Point_0 of array2: 5, 10Point_1 of array2: 15, 20After the moving of pointsArray1:Point_0 of array2: 5, 10Point_1 of array2: 15, 20Deleting.Destructor called.Destructor called.Deletin

308、g.Destructor called.Destructor called.3892021/6/4389拷贝前pointsArray1的数组元素占用的内存pointsnumberOfPointspointsArray1拷贝后pointsnumberOfPointspointsArray1pointsArray1的 数组元素占用的内存pointsnumberOfPointspointsArray23902021/6/4390C+语言程序设计清华大学 郑莉用字符数组存储和处理字符串用字符数组存储和处理字符串字符数组的声明和引用例:staticcharstr8=112,114,111,103,114

309、,97,109,0;staticcharstr8=p,r,o,g,r,a,m,0;staticcharstr8=program;staticcharstr=program;字符串字符串常量,例如:china没有字符串变量,用字符数组来存放字符串字符串以0为结束标志字符数组的初始化字符串2021/6/4391C+语言程序设计清华大学 郑莉例例6-22 输出一个字符串输出一个字符串#includeusingnamespacestd;voidmain()staticcharc10=I,a,m,a,b,o,y;inti;for(i=0;i10;i+)coutci;coutendl;运行结果:Iamab

310、oy字符串2021/6/4392C+语言程序设计清华大学 郑莉例例6-23输出一个钻石图形输出一个钻石图形 #includeusingnamespacestd;voidmain()staticchardiamond5=,*,*,*,*,*,*,*,*;inti,j;for(i=0;i5;i+)for(j=0;j5&diamondij!=0;j+)coutdiamondij;coutendl;运行结果: * * * * * * * 字符串2021/6/4393C+语言程序设计清华大学 郑莉字符串的输入字符串的输入/输出输出l方法方法逐个字符输入输出将整个字符串一次输入或输出例:char c=Ch

311、ina; coutstr1str2str3; 运行时输入数据: How are you?内存中变量状态如下:str1:How0str2:are0str3:you?03952021/6/4395若改为: static char str13; cinstr; 运行时输入数据: How are you?内存中变量str内容如下:str:How03962021/6/4396C+语言程序设计清华大学 郑莉用字符数组存储和处理字符串用字符数组存储和处理字符串注意!若有如下声明注意!若有如下声明:char a4, *p1, *p2;错误的:a=abc;cinp1;正确的:p1=abc;p2=a;cinp2;

312、字符串2021/6/4397C+语言程序设计清华大学 郑莉整行输入字符串整行输入字符串lcin.getline(字符数组名字符数组名St, 字符个数字符个数N, 结束符结束符);功能:一次连续读入多个字符(可以包括空格),直到读满N个,或遇到指定的结束符(默认为n)。读入的字符串存放于字符数组St中。读取但不存储结束符。lcin.get(字符数组名字符数组名St, 字符个数字符个数N, 结束符结束符);功能:一次连续读入多个字符(可以包括空格),直到读满N个,或遇到指定的结束符(默认为n)。读入的字符串存放于字符数组St中。既不读取也不存储结束符。字符串2021/6/4398C+语言程序设计清

313、华大学 郑莉整行输入字符串举例整行输入字符串举例#include using namespace std;void main (void) char city80;char state80;int i;for (i = 0; i 2; i+) cin.getline(city,80,); cin.getline(state,80,n); cout City: city State: state endl;字符串2021/6/4399C+语言程序设计清华大学 郑莉运行结果运行结果Beijing,ChinaCity: Beijing Country: ChinaShanghai,ChinaCity

314、: Shanghai Country: China2021/6/4400C+语言程序设计清华大学 郑莉字符串处理函数字符串处理函数strcat(连接),(连接),strcpy(复制),(复制),strcmp(比较),(比较),strlen(求长度),(求长度), strlwr(转换为小写),转换为小写),strupr(转换为大写)(转换为大写)头文件头文件字符串2021/6/4401C+语言程序设计清华大学 郑莉例例6.21 string类应用举例类应用举例#include #include using namespace std ;void trueFalse(int x) cout (x?

315、 True: False) endl;字符串2021/6/4402void main() string S1=DEF, S2=123; char CP1 =ABC; char CP2 =DEF; cout S1 is S1 endl; cout S2 is S2 endl; coutlength of S2:S2.length()endl; cout CP1 is CP1 endl; cout CP2 is CP2 endl; cout S1=CP1 returned ; trueFalse(S1=CP1); cout CP2=S1 returned ; trueFalse(CP2=S1);

316、S2+=S1; coutS2=S2+S1:S2endl; coutlength of S2:S2.length()endl;4032021/6/4403第九章第九章 群体类群体类和群体数据的组织和群体数据的组织西南林学院西南林学院 鲁莹鲁莹C+语言程序设计2021/6/4404C+语言程序设计西南林学院 鲁莹本章主要内容本章主要内容l模板模板l群体类群体类l群体数据的组织群体数据的组织2021/6/4405C+语言程序设计西南林学院 鲁莹第一部分第一部分模板模板l函数模板函数模板l类模板类模板2021/6/4406C+语言程序设计西南林学院 鲁莹函数模板函数模板l函数模板可以用来创建一个通用功

317、能函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,进一的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。步简化重载函数的函数体设计。l声明方法:声明方法:template函数声明函数模板2021/6/4407C+语言程序设计西南林学院 鲁莹求绝对值函数的模板求绝对值函数的模板#includeusing namespace std;templateT abs(T x) return x0?-x:x; void main() int n=-5; double d=-5.5; coutabs(n)endl; coutabs(d)endl;函数模板运行结果:运行结果:55.520

318、21/6/4408C+语言程序设计西南林学院 鲁莹求绝对值函数的模板分析求绝对值函数的模板分析l编译器从调用编译器从调用abs()时实参的类型,推时实参的类型,推导出函数模板的类型参数。例如,对导出函数模板的类型参数。例如,对于调用表达式于调用表达式abs(n),由于实参,由于实参n为为int型,所以推导出模板中类型参数型,所以推导出模板中类型参数T为为int。l当类型参数的含义确定后,编译器将当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数:以函数模板为样板,生成一个函数:int abs(int x) return x0?-x:x; 函数模板2021/6/4409C+语言程序设

319、计西南林学院 鲁莹类模板的作用类模板的作用使用类模板使用户可以为类声明一使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括基本的返回值,能取任意类型(包括基本类型的和用户自定义类型)。类型的和用户自定义类型)。类模板2021/6/4410C+语言程序设计西南林学院 鲁莹类模板的声明类模板的声明l类模板:类模板:templateclass类名类成员声明l如果需要在类模板以外定义其成员如果需要在类模板以外定义其成员函数,则要采用以下的形式:函数,则要采用以下的形式

320、:template类型名类名:函数名(参数表)类模板2021/6/4411C+语言程序设计西南林学院 鲁莹例例9-2 类模板应用举例类模板应用举例#include #include using namespace std;/ 结构体结构体Studentstruct Student int id; /学号学号 float gpa; /平均分平均分; 类模板2021/6/4412template /类模板:实现对任意类型数据进行存取类模板:实现对任意类型数据进行存取class Store private: T item; / 用于存放任意类型的数据用于存放任意类型的数据 int haveValue

321、; / 用于标记用于标记item是否已被存入内容是否已被存入内容 public: Store(void); / 默认形式(无形参)的构造函数默认形式(无形参)的构造函数 T GetElem(void); /提取数据函数提取数据函数 void PutElem(T x); /存入数据函数存入数据函数;/ 默认形式构造函数的实现默认形式构造函数的实现template Store:Store(void): haveValue(0) 4132021/6/4413template / 提取数据函数的实现提取数据函数的实现T Store:GetElem(void) / 如果试图提取未初始化的数据,则终止程序

322、如果试图提取未初始化的数据,则终止程序 if (haveValue = 0) cout No item present! endl; exit(1); return item; / 返回返回item中存放的数据中存放的数据 template / 存入数据函数的实现存入数据函数的实现 void Store:PutElem(T x) haveValue+; / 将将haveValue 置为置为 TRUE,表示,表示item中已存入数值中已存入数值 item = x; / 将将x值存入值存入item4142021/6/4414void main(void) Student g= 1000, 23;

323、Store S1, S2; Store S3; Store D; S1.PutElem(3); S2.PutElem(-7); cout S1.GetElem() S2.GetElem() endl; S3.PutElem(g); cout The student id is S3.GetElem().id endl; cout Retrieving object D ;cout D.GetElem() endl; /输出对象输出对象D的数据成员的数据成员/ 由于由于D未经初始化未经初始化,在执行函数在执行函数D.GetElement()时出错时出错4152021/6/4415C+语言程序设计

324、西南林学院 鲁莹第二部分第二部分群群体数据体数据l线性群体线性群体线性群体的概念直接访问群体-数组类顺序访问群体-链表类栈类队列类2021/6/4416C+语言程序设计西南林学院 鲁莹群体的概念群体的概念群体群体是指由多个数据元素组成的集是指由多个数据元素组成的集合体。群体可以分为两个大类:合体。群体可以分为两个大类:线性群线性群体体和和非线性群体非线性群体。线性群体中的元素按位置排列有序,线性群体中的元素按位置排列有序,可以区分为第一个元素、第二个元素等。可以区分为第一个元素、第二个元素等。非线性群体不用位置顺序来标识元非线性群体不用位置顺序来标识元素。素。2021/6/4417C+语言程序

325、设计西南林学院 鲁莹线性群体的概念线性群体的概念线性群体中的元素次序与其位置关线性群体中的元素次序与其位置关系是对应的。在线性群体中,又可按照系是对应的。在线性群体中,又可按照访问元素的不同方法分为访问元素的不同方法分为直接访问直接访问、顺顺序访问序访问和和索引访问索引访问。在本章我们只介绍直接访问和顺序在本章我们只介绍直接访问和顺序访问。访问。第一个元素第二个元素第三个元素最后一个元素2021/6/4418C+语言程序设计西南林学院 鲁莹数组数组l静态数组是具有固定元素个数的群体,其静态数组是具有固定元素个数的群体,其中的元素可以通过下标直接访问。中的元素可以通过下标直接访问。缺点:大小在编

326、译时就已经确定,在运行时无法修改。l动态数组由一系列位置连续的,任意数量动态数组由一系列位置连续的,任意数量相同类型的元素组成。相同类型的元素组成。优点:其元素个数可在程序运行时改变。l动态数组类模板:例动态数组类模板:例9-3(9_3.h)直接访问的线性群体2021/6/4419#ifndef ARRAY_CLASS#define ARRAY_CLASSusing namespace std;#include #include #ifndef NULLconst int NULL = 0;#endif / NULLenum ErrorType invalidArraySize, memory

327、AllocationError, indexOutOfRange ;char *errorMsg = Invalid array size, Memory allocation error, Invalid index: ;动态数组类模板程序4202021/6/4420template class Array private: T* alist; int size; void Error(ErrorType error,int badIndex=0) const; public: Array(int sz = 50); Array(const Array& A); Array(void); A

328、rray& operator= (const Array& rhs); T& operator(int i); operator T* (void) const; int ListSize(void) const; void Resize(int sz); ;4212021/6/4421C+语言程序设计西南林学院 鲁莹数组类模板的构造函数数组类模板的构造函数/ 构造函数构造函数template Array:Array(int sz) if (sz = 0) /sz为数组大小(元素个数),若小于为数组大小(元素个数),若小于0,则输出错误信息,则输出错误信息 Error(invalidArray

329、Size); size = sz; / 将元素个数赋值给变量将元素个数赋值给变量size alist = new Tsize; /动态分配动态分配size个个T类型的元素空间类型的元素空间 if (alist = NULL) /如果分配内存不成功,输出错误信息如果分配内存不成功,输出错误信息 Error(memoryAllocationError);直接访问的线性群体2021/6/4422C+语言程序设计西南林学院 鲁莹数组类的拷贝构造函数数组类的拷贝构造函数template Array:Array(const Array& X) int n = X.size; size = n; alist

330、 = new Tn; if (alist = NULL) Error(memoryAllocationError); T* srcptr = X.alist; / X.alist是对象是对象X的数组首地址的数组首地址 T* destptr = alist; / alist是本对象中的数组首地址是本对象中的数组首地址 while (n-) / 逐个复制数组元素逐个复制数组元素 *destptr+ = *srcptr+;直接访问的线性群体2021/6/4423C+语言程序设计西南林学院 鲁莹浅拷贝浅拷贝alistsizeAA的数组元素占用的内存拷贝前alistsizeAA的数组元素占用的内存拷贝后

331、alistsizeBvoidmain(void)ArrayA(10);.ArrayB(A);.templateArray:Array(constArray&X)size=X.size;alist=X.alist;2021/6/4424C+语言程序设计西南林学院 鲁莹深拷贝深拷贝alistsizeAA的数组元素占用的内存拷贝前alistsizeAA的数组元素占用的内存拷贝后alistsizeBB的数组元素占用的内存2021/6/4425C+语言程序设计西南林学院 鲁莹数组类的重载数组类的重载=运算符函数运算符函数template Array& Array:operator= (const Arr

332、ay& rhs) int n = rhs.size; if (size != n) delete alist; alist = new Tn; if (alist = NULL) Error(memoryAllocationError); size = n; T* destptr = alist; T* srcptr = rhs.alist; while (n-) *destptr+ = *srcptr+; return *this;直接访问的线性群体2021/6/4426C+语言程序设计西南林学院 鲁莹数组类的重载下标操作符函数数组类的重载下标操作符函数template T& Array:o

333、perator (int n) / 检查下标是否越界检查下标是否越界 if (n size-1) Error(indexOutOfRange,n); / 返回下标为返回下标为n的数组元素的数组元素 return alistn;直接访问的线性群体2021/6/4427C+语言程序设计西南林学院 鲁莹为什么有的函数返回引用为什么有的函数返回引用l如果一个函数的返回值是一个对象的如果一个函数的返回值是一个对象的值,它就被认为是一个常量,不能成值,它就被认为是一个常量,不能成为左值。为左值。l如果返回值为引用。由于引用是对象如果返回值为引用。由于引用是对象的别名,所以通过引用当然可以改变的别名,所以通

334、过引用当然可以改变对象的值。对象的值。直接访问的线性群体2021/6/4428C+语言程序设计西南林学院 鲁莹重载指针转换操作符重载指针转换操作符template Array:operator T* (void) const / 返回当前对象中私有数组的首地址返回当前对象中私有数组的首地址 return alist;直接访问的线性群体2021/6/4429C+语言程序设计西南林学院 鲁莹指针转换运算符的作用指针转换运算符的作用#include using namespace std;void main() int a10; void read(int *p, int n); read(a, 1

335、0);void read(int *p, int n) for (int i=0; ipi;void main() Array a(10); void read(int *p, n); read(a, 10);void read(int *p, int n) for (int i=0; ipi;直接访问的线性群体2021/6/4430C+语言程序设计西南林学院 鲁莹Array类的应用类的应用l例例9-4求范围求范围2N中的质数,中的质数,N在程序在程序运行时由键盘输入。运行时由键盘输入。直接访问的线性群体2021/6/4431#include #include #include 9_3.hus

336、ing namespace std;void main(void) Array A(10); int n; int primecount = 0, i, j; cout = 2 as upper limit for prime numbers: ; cin n; Aprimecount+ = 2; / 2是一个质数是一个质数 for(i = 3; i n; i+) if (primecount = A.ListSize() A.Resize(primecount + 10); if (i % 2 = 0) continue; j = 3; while (j i/2) Aprimecount+

337、= i; for (i = 0; i primecount; i+) cout setw(5) Ai; if (i+1) % 10 = 0) cout endl; cout endl;4322021/6/4432C+语言程序设计西南林学院 鲁莹链表链表l链表是一种动态数据结构,可以用来链表是一种动态数据结构,可以用来表示顺序访问的线性群体。表示顺序访问的线性群体。l链表是由系列链表是由系列结点结点组成的,结点可以组成的,结点可以在运行时动态生成。在运行时动态生成。l每一个结点包括每一个结点包括数据域数据域和指向链表中和指向链表中下一个结点的下一个结点的指针指针(即下一个结点的(即下一个结点的地

338、址)。如果链表每个结点中只有一地址)。如果链表每个结点中只有一个指向后继结点的指针,则该链表称个指向后继结点的指针,则该链表称为单链表。为单链表。顺序访问的线性群体2021/6/4433C+语言程序设计西南林学院 鲁莹单链表单链表data1data2data3datanNULLheadrear顺序访问的线性群体2021/6/4434C+语言程序设计西南林学院 鲁莹单链表的结点类模板单链表的结点类模板template class Node private: Node *next; public: T data; Node(const T& item,Node* ptrnext = NULL);

339、void InsertAfter(Node *p); Node *DeleteAfter(void); Node *NextNode(void) const; 顺序访问的线性群体2021/6/4435C+语言程序设计西南林学院 鲁莹在结点之后插入一个结点在结点之后插入一个结点data1data2pdatatemplate void Node:InsertAfter(Node *p) /p节点指针域指向当前节点的后继节点节点指针域指向当前节点的后继节点 p-next = next; next = p; /当前节点的指针域指向当前节点的指针域指向p 顺序访问的线性群体2021/6/4436C+语言

340、程序设计西南林学院 鲁莹 删除结点之后的结点删除结点之后的结点顺序访问的线性群体data1data2data3Node *Node:DeleteAfter(void) Node *tempPtr = next; if (next = NULL) return NULL; next = tempPtr-next; return tempPtr; tempPtr2021/6/4437C+语言程序设计西南林学院 鲁莹链表的基本操作链表的基本操作l生成结点生成结点l插入结点插入结点l查找结点查找结点l删除结点删除结点l遍历链表遍历链表l清空链表清空链表顺序访问的线性群体2021/6/4438C+语言程

341、序设计西南林学院 鲁莹链表类模板链表类模板(例例9-6)/9_6.h#ifndef LINKEDLIST_CLASS#define LINKEDLIST_CLASS#include #include using namespace std;#ifndef NULLconst int NULL = 0;#endif / NULL#include 9_5.h顺序访问的线性群体2021/6/4439template class LinkedList private: Node *front, *rear; Node *prevPtr, *currPtr; int size; int position

342、; Node *GetNode(const T& item, Node *ptrNext=NULL); void FreeNode(Node *p); void CopyList(const LinkedList& L);4402021/6/4440 public: LinkedList(void); LinkedList(const LinkedList& L); LinkedList(void); LinkedList& operator= (const LinkedList& L); int ListSize(void) const; int ListEmpty(void) const;

343、 void Reset(int pos = 0); void Next(void); int EndOfList(void) const; int CurrentPosition(void) const; 4412021/6/4441 void InsertFront(const T& item); void InsertRear(const T& item); void InsertAt(const T& item); void InsertAfter(const T& item); T DeleteFront(void); void DeleteAt(void); T& Data(void

344、); void ClearList(void);#endif / LINKEDLIST_CLASS4422021/6/4442C+语言程序设计西南林学院 鲁莹链表类应用举例链表类应用举例(例例9-7)#include using namespace std;#include 9_6.h#include 9_6.cppvoid main(void) LinkedList Link; int i, key, item; for (i=0;i item; Link.InsertFront(item);顺序访问的线性群体2021/6/4443 cout List: ; Link.Reset(); wh

345、ile(!Link.EndOfList() cout Link.Data() ; Link.Next(); cout endl; cout key; Link.Reset();4442021/6/4444 while (!Link.EndOfList() if(Link.Data() = key) Link.DeleteAt(); Link.Next(); cout List: ; Link.Reset(); while(!Link.EndOfList() cout Link.Data() ; Link.Next(); cout endl;4452021/6/4445C+语言程序设计西南林学院

346、 鲁莹特殊的线性群体特殊的线性群体栈栈栈是只能从一端访问的线性群体,栈是只能从一端访问的线性群体,可以访问的这一端称栈顶,另一端称栈可以访问的这一端称栈顶,另一端称栈底。底。ana2a1入栈出栈栈顶栈底特殊的线性群体栈2021/6/4446C+语言程序设计西南林学院 鲁莹栈的应用举例栈的应用举例函数调用函数调用特殊的线性群体栈main调fun(参数)结束fun(参数)返回参数当前现场返回地址入栈当前现场返回地址出栈参数出栈当前现场返回地址2021/6/4447C+语言程序设计西南林学院 鲁莹栈的应用举例栈的应用举例表达式处理表达式处理ba/a/b+c*d(a)t1+a/b+c*dt1=a/b(

347、b)dct1*+a/b+c*d(c)t3a/b+c*dt3=t1+t2(e)t2t1+a/b+c*dt2=c*d(d)特殊的线性群体栈2021/6/4448C+语言程序设计西南林学院 鲁莹栈的基本状态栈的基本状态l栈空栈空栈中没有元素l栈满栈满栈中元素个数达到上限l一般状态一般状态栈中有元素,但未达到栈满状态特殊的线性群体栈2021/6/4449栈顶ana1a0入栈出栈数组下标maxn10一般状态栈顶入栈出栈数组下标初始状态(栈空)maxn10栈顶amaxana1a0入栈出栈数组下标maxn10栈满状态4502021/6/4450C+语言程序设计西南林学院 鲁莹栈的基本操作栈的基本操作l初始化

348、初始化l入栈入栈l出栈出栈l清空栈清空栈l访问栈顶元素访问栈顶元素l检测栈的状态(满、空)检测栈的状态(满、空)特殊的线性群体栈2021/6/4451C+语言程序设计西南林学院 鲁莹栈类模板栈类模板(例例9-8)特殊的线性群体栈/9-8.h#ifndef STACK_CLASS#define STACK_CLASS#include #include using namespace std;const int MaxStackSize = 50; template class Stack private: T stacklistMaxStackSize; int top; public: Sta

349、ck (void); void Push (const T& item); T Pop (void); void ClearStack(void); T Peek (void) const; int StackEmpty(void) const; int StackFull(void) const;/类的实现略类的实现略2021/6/4452C+语言程序设计西南林学院 鲁莹栈的应用栈的应用l例例9.9 一个简单的整数计算器一个简单的整数计算器实现一个简单的整数计算器,能够进行加、减、乘、除和乘方运算。使用时算式采用后缀输入法,每个操作数、操作符之间都以空白符分隔。例如,若要计算3+5则输入35

350、+。乘方运算符用表示。每次运算在前次结果基础上进行,若要将前次运算结果清除,可键入c。当键入q时程序结束。l9-9.h 9-9.cpp特殊的线性群体栈2021/6/4453/9_9.h#include #include #include #include using namespace std;enum Boolean False, True;#include 9_8.h class Calculator private: Stack S; void Enter(int num); Boolean GetTwoOperands(int& opnd1, int& opnd2); void Com

351、pute(char op); public: void Run(void); void Clear(void); ;4542021/6/4454void Calculator:Enter(int num) S.Push(num); Boolean Calculator:GetTwoOperands(int& opnd1, int& opnd2) if (S.StackEmpty() cerr Missing operand! endl; return False; opnd1 = S.Pop(); if (S.StackEmpty() cerr Missing operand! endl; r

352、eturn False; opnd2 = S.Pop(); return True;4552021/6/4455void Calculator:Compute(char op) Boolean result; int operand1, operand2;result = GetTwoOperands(operand1, operand2); if (result) switch(op) case +: S.Push(operand2+operand1); break; case -: S.Push(operand2-operand1); break; case *: S.Push(opera

353、nd2*operand1); break; case /: if (operand1 = 0) cerr Divide by 0! endl; S.ClearStack(); else S.Push(operand2/operand1); break; case : S.Push(pow(operand2,operand1); break; cout=S.Peek() c, *c != q) switch(*c) case c: S.ClearStack(); break; case -: if (strlen(c)1) Enter(atoi(c); else Compute(*c); bre

354、ak; case +: case *: case /: case : Compute(*c); break; default: Enter(atoi(c); break; 4572021/6/4457void Calculator:Clear(void) S.ClearStack(); /9_9.cpp#include 9-9.hvoid main(void) Calculator CALC; CALC.Run();4582021/6/4458C+语言程序设计西南林学院 鲁莹特殊的线性群体特殊的线性群体队列队列队列是只能向一端添加元素,从另队列是只能向一端添加元素,从另一端删除元素的线性群体一

355、端删除元素的线性群体a1a2an-1an队头队尾入队出队a02021/6/4459C+语言程序设计西南林学院 鲁莹队列的基本状态队列的基本状态l队空队空队列中没有元素l队满队满队列中元素个数达到上限l一般状态一般状态队列中有元素,但未达到队满状态特殊的线性群体队列2021/6/4460a0a1an-1an队头队尾入队出队数组下标01n-1nmax(一般状态)队头队尾入队出队数组下标01n-1nmax(队空状态)a0a1an-1anamax队头队尾入队出队数组下标01n-1nmax(队满状态)元素移动方向元素移动方向4612021/6/4461C+语言程序设计西南林学院 鲁莹循环队列循环队列在想

356、象中将数组弯曲成环形,元素在想象中将数组弯曲成环形,元素出队时,后继元素不移动,每当队尾达出队时,后继元素不移动,每当队尾达到数组最后一个元素时,便再回到数组到数组最后一个元素时,便再回到数组开头。开头。特殊的线性群体队列2021/6/44621234m-1m-2m-30amam+1am+2a3队头队尾a4am-2am-3am-1队满状态元素个数=m1234m-1m-2m-30队尾队头队空状态元素个数=0队尾1234m-1m-2m-30a0a1a2a3队头一般状态4632021/6/4463C+语言程序设计西南林学院 鲁莹例例9-10 队列类模板队列类模板特殊的线性群体队列#ifndef QU

357、EUE_CLASS#define QUEUE_CLASS#include #include using namespace std;const int MaxQSize = 50; template class Queue private: int front, rear, count; T qlistMaxQSize; public: Queue (void); void QInsert(const T& item); T QDelete(void); void ClearQueue(void); T QFront(void) const; int QLength(void) const;

358、int QEmpty(void) const; int QFull(void) const; ;/成员函数的实现略成员函数的实现略2021/6/4464C+语言程序设计西南林学院 鲁莹第三部分第三部分群群体数据的组织体数据的组织l插入排序插入排序l选择排序选择排序l交换排序交换排序l顺序查找顺序查找l折半查找折半查找2021/6/4465C+语言程序设计西南林学院 鲁莹排序(排序(sorting)l排序排序是计算机程序设计中的一种重要操作,是计算机程序设计中的一种重要操作,它的功能是将一个它的功能是将一个数据元素数据元素的任意序列,重的任意序列,重新排列成一个按新排列成一个按关键字关键字有序的

359、序列。有序的序列。数据元素:数据的基本单位。在计算机中通常作为一个整体进行考虑。一个数据元素可由若干数据项组成。关键字:数据元素中某个数据项的值,用它可以标识(识别)一个数据元素。l在排序过程中需要完成两种基本操作:在排序过程中需要完成两种基本操作:比较两个数的大小调整元素在序列中的位置群体数据的组织2021/6/4466C+语言程序设计西南林学院 鲁莹内部排序与外部排序内部排序与外部排序l内部排序:内部排序:待排序的数据元素存放在待排序的数据元素存放在计算机内存中进行的排序过程。计算机内存中进行的排序过程。l外部排序:外部排序:待排序的数据元素数量很待排序的数据元素数量很大,以致内存存中一次

360、不能容纳全部大,以致内存存中一次不能容纳全部数据,在排序过程中尚需对外存进行数据,在排序过程中尚需对外存进行访问的排序过程。访问的排序过程。群体数据的组织2021/6/4467C+语言程序设计西南林学院 鲁莹内部排序方法内部排序方法l插入排序插入排序l选择排序选择排序l交换排序交换排序群体数据的组织2021/6/4468C+语言程序设计西南林学院 鲁莹插入排序的基本思想插入排序的基本思想l每一步将一个待排序元素按其关键字值的大小插入到已排每一步将一个待排序元素按其关键字值的大小插入到已排序序列的适当位置上,直到待排序元素插入完为止。序序列的适当位置上,直到待排序元素插入完为止。初始状态:初始状

361、态: 5 4 10 20 12 3 5 4 10 20 12 3插入操作:插入操作:1 1 44 4 5 10 20 12 3 4 5 10 20 12 32 2 1010 4 5 10 20 12 3 4 5 10 20 12 33 3 2020 4 5 10 20 12 3 4 5 10 20 12 34 4 1212 4 5 10 12 20 3 4 5 10 12 20 35 5 33 3 4 5 10 12 20 3 4 5 10 12 202021/6/4469C+语言程序设计西南林学院 鲁莹直接插入排序直接插入排序l在插入排序过程中,由于寻找插入位置的在插入排序过程中,由于寻找插

362、入位置的方法不同又可以分为不同的插入排序算法,方法不同又可以分为不同的插入排序算法,这里我们只介绍最简单的直接插入排序算这里我们只介绍最简单的直接插入排序算法。法。l例例9-11 直接插入排序函数模板(直接插入排序函数模板(9_11.h)群体数据的组织2021/6/4470template void InsertionSort(T A, int n) int i, j; T temp; for (i = 1; i 0 & temp Aj-1) Aj = Aj-1; j-; Aj = temp; 直接插入排序函数模板(9_11.h)4712021/6/4471C+语言程序设计西南林学院 鲁莹选择

363、排序的基本思想选择排序的基本思想每次从待排序序列中选择一个关键字最小的元素,每次从待排序序列中选择一个关键字最小的元素,(当需要按关键字升序排列时),顺序排在已排序序列的(当需要按关键字升序排列时),顺序排在已排序序列的最后,直至全部排完。最后,直至全部排完。5 4 10 20 12 5 4 10 20 12 3 3 初始状态:初始状态:3 3 4 4 10 20 12 5 10 20 12 53 4 10 20 12 3 4 10 20 12 5 5 第 i i 次选择后,将选出的那个记录与第 i i 个记录做交换交换。3 4 5 20 12 3 4 5 20 12 1010 . .2021

364、/6/4472C+语言程序设计西南林学院 鲁莹直接选择排序直接选择排序l在选择类排序方法中,从待排序序列在选择类排序方法中,从待排序序列中选择元素的方法不同,又分为不同中选择元素的方法不同,又分为不同的选择排序方法,其中最简单的是通的选择排序方法,其中最简单的是通过顺序比较找出待排序序列中的最小过顺序比较找出待排序序列中的最小元素,称为直接选择排序。元素,称为直接选择排序。l例例9-12 直接选择排序函数模板(直接选择排序函数模板(9-12.h)群体数据的组织2021/6/4473template void Swap (T &x, T &y) T temp; temp = x; x = y;

365、y = temp;template void SelectionSort(T A, int n) int smallIndex; int i, j; for (i = 0; i n-1; i+) smallIndex = i; for (j = i+1; j n; j+) if (Aj AsmallIndex) smallIndex = j; Swap(Ai, AsmallIndex); 直接选择排序函数模板(9-12.h)4742021/6/4474C+语言程序设计西南林学院 鲁莹交换排序的基本思想交换排序的基本思想两两比较待排序序列中的元素,并两两比较待排序序列中的元素,并交换不满足顺序要

366、求的各对元素,直到交换不满足顺序要求的各对元素,直到全部满足顺序要求为止。全部满足顺序要求为止。群体数据的组织2021/6/4475C+语言程序设计西南林学院 鲁莹最简单的交换排序方法最简单的交换排序方法 起泡排序起泡排序对具有对具有n个元素的序列按升序进行起泡排序的个元素的序列按升序进行起泡排序的步骤:步骤:首先将第一个元素与第二个元素进行比较,若为逆序,则将两元素交换。然后比较第二、第三个元素,依次类推,直到第n-1和第n个元素进行了比较和交换。此过程称为第一趟起泡排序。经过第一趟,最大的元素便被交换到第n个位置。对前n-1个元素进行第二趟起泡排序,将其中最大元素交换到第n-1个位置。如此

367、继续,直到某一趟排序未发生任何交换时,排序完毕。对n个元素的序列,起泡排序最多需要进行n-1趟。群体数据的组织2021/6/4476C+语言程序设计西南林学院 鲁莹起泡排序举例起泡排序举例对整数序列对整数序列 8 5 2 4 3 按升序排序按升序排序8524352438243582345823458初始状态第一趟结果第二趟结果第三趟结果第四趟结果小的逐渐上升每趟沉下一个最大的群体数据的组织2021/6/4477C+语言程序设计西南林学院 鲁莹例例9-13 起泡排序函数模板起泡排序函数模板template void Swap (T &x, T &y) T temp; temp = x; x =

368、y; y = temp;template void BubbleSort(T A, int n) int i,j; int lastExchangeIndex; i = n-1; while (i 0) lastExchangeIndex = 0; for (j = 0; j i; j+) if (Aj+1 Aj) Swap(Aj,Aj+1); lastExchangeIndex = j; i = lastExchangeIndex; 群体数据的组织2021/6/4478C+语言程序设计西南林学院 鲁莹顺序查找顺序查找l其基本思想其基本思想从序列的首元素开始,逐个元素与待查找的关键字进行比较,

369、直到找到相等的。若整个序列中没有与待查找关键字相等的元素,就是查找不成功。l顺序查找函数模板顺序查找函数模板例9-14群体数据的组织2021/6/4479template int SeqSearch(T list, int n, T key) for(int i=0;i n;i+) if (listi = key) return i; return -1; 顺序查找函数模板4802021/6/4480C+语言程序设计西南林学院 鲁莹折半查找的基本思想折半查找的基本思想对于已按关键字排序的序列,经过一次比较,可将序列分割成两部分,然后只在有可能包含待查元素的一部分中继续查找,并根据试探结果继续分

370、割,逐步缩小查找范围,直至找到或找不到为止。群体数据的组织2021/6/4481C+语言程序设计西南林学院 鲁莹折半查找举例折半查找举例用折半查找法,在下列序列中查找值为用折半查找法,在下列序列中查找值为2121的元素:的元素:L=1513192137566475808892H=11M =INT(L+H)/2)=6513192137L=1H=M-1=5M=INT(L+H)/2)=3M2137HL=M+1=4LM=INT(L+H)/2)=4M2021/6/4482C+语言程序设计西南林学院 鲁莹例例10-5 折半查找函数模板折半查找函数模板template int BinSearch(T lis

371、t, int n, T key) int mid, low, high; T midvalue; low=0; high=n-1; while (low = high) mid = (low+high)/2; midvalue = listmid; if (key = midvalue) return mid; else if (key midvalue) high = mid-1; else low = mid+1; return -1; 群体数据的组织2021/6/4483异常处理 西南林学院西南林学院 鲁莹鲁莹2021/6/4484程序设计的要求之一就是程序的健程序设计的要求之一就是程序

372、的健壮性。希望程序在运行时能够不出壮性。希望程序在运行时能够不出或者少出问题。但是,在程序的实或者少出问题。但是,在程序的实际运行时,总会有一些因素会导致际运行时,总会有一些因素会导致程序不能正常运行。异常处理程序不能正常运行。异常处理(Exception Handling)就是要提)就是要提出或者是研究一种机制,能够较好出或者是研究一种机制,能够较好的处理程序不能正常运行的问题。的处理程序不能正常运行的问题。2021/6/44851、异常和异常处理、异常和异常处理异常(异常(Exceptions)是程序在运行时可能)是程序在运行时可能出现的会导致程序运行终止的错误。出现的会导致程序运行终止的

373、错误。编译系统检查出来的语法错误,导致程序编译系统检查出来的语法错误,导致程序运行结果不正确的逻辑错误,都不属于异运行结果不正确的逻辑错误,都不属于异常的范围。常的范围。异常是一个可以正确运行的程序在运行中异常是一个可以正确运行的程序在运行中可能发生的错误。可能发生的错误。2021/6/44861、异常和异常处理、异常和异常处理常见的异常,如常见的异常,如:系统资源不足。如内存不足,不可以动态申请系统资源不足。如内存不足,不可以动态申请内存空间;磁盘空间不足,不能打开新的输出内存空间;磁盘空间不足,不能打开新的输出文件,等。文件,等。用户操作错误导致运算关系不正确。如出现分用户操作错误导致运算

374、关系不正确。如出现分母为母为0,数学运算溢出,数组越界,参数类型,数学运算溢出,数组越界,参数类型不能转换,等。不能转换,等。2021/6/44871、异常和异常处理、异常和异常处理异常有以下的一些特点:异常有以下的一些特点:偶然性。程序运行中,异常并不总是会发生的。偶然性。程序运行中,异常并不总是会发生的。可预见性。异常的存在和出现是可以预见的。可预见性。异常的存在和出现是可以预见的。 严重性。一旦异常发生,程序可能终止,或者严重性。一旦异常发生,程序可能终止,或者运行的结果不可预知。运行的结果不可预知。2021/6/44881、异常和异常处理、异常和异常处理对于程序中的异常,通常有三种处理

375、对于程序中的异常,通常有三种处理的方法:的方法:不作处理。很多程序实际上就是不处理异常的。不作处理。很多程序实际上就是不处理异常的。 发布相应的错误信息,然后,终止程序的运行。发布相应的错误信息,然后,终止程序的运行。在在C语言的程序中,往往就是这样处理的。语言的程序中,往往就是这样处理的。 适当的处理异常,一般应该使程序可以继续运适当的处理异常,一般应该使程序可以继续运行。行。2021/6/44891、异常和异常处理、异常和异常处理一般来说,异常处理(一般来说,异常处理(Exception Handling)就是在程序运行时对异常)就是在程序运行时对异常进行检测和控制。进行检测和控制。在在C

376、+中,异常处理(中,异常处理(EH)就是用)就是用C+提供的提供的trythrowcatch的模式的模式进行异常处理的机制。进行异常处理的机制。2021/6/44902021/6/44912021/6/44921、异常和异常处理、异常和异常处理如出现分母为如出现分母为0 的情况,运行将出现以下结果:的情况,运行将出现以下结果:2021/6/44931、异常和异常处理、异常和异常处理这个程序中,对于除数为这个程序中,对于除数为0的处理有这的处理有这样的特点:样的特点:异常的检测和处理都是在一个程序模块异常的检测和处理都是在一个程序模块(dividedivide函数)中进行的;函数)中进行的;由于

377、函数的返回值是由于函数的返回值是doubledouble型的数据,型的数据,因此,即使检测到除数为因此,即使检测到除数为0 0的情况,也不的情况,也不能通过返回值来反映这个异常。只能调能通过返回值来反映这个异常。只能调用函数用函数abortabort终止程序的运行。终止程序的运行。2021/6/44942、C+异常处理机制异常处理机制C+处理异常有两个基本的做法:异常的检测和处理是在不同的代码段中进行的。异常的检测和处理是在不同的代码段中进行的。一般的是在一般的是在“try”部分检测异常,部分检测异常,“catch”部分处部分处理异常。理异常。由于异常的检测和处理不是在同一个代码段中由于异常的

378、检测和处理不是在同一个代码段中进行的,在检测异常和处理异常的代码段之间进行的,在检测异常和处理异常的代码段之间需要有一种传递异常信息的机制,在需要有一种传递异常信息的机制,在C+中是中是通过通过“对象对象”来传递异常的。这种对象可以是一来传递异常的。这种对象可以是一种简单的数据(如整数),也可以是系统定义种简单的数据(如整数),也可以是系统定义或用户自定义的类的对象。或用户自定义的类的对象。2021/6/44952、C+异常处理机制异常处理机制一般来说,异常处理(一般来说,异常处理(Exception Handling)就是在程序运行时对异常)就是在程序运行时对异常进行检测和控制。进行检测和控

379、制。在在C+中,异常处理(中,异常处理(EH)就是用)就是用C+提供的提供的trythrowcatch的模式的模式进行异常处理的机制。进行异常处理的机制。2021/6/44962、C+异常处理机制异常处理机制在在C+术语中,异常(术语中,异常(Exception,注意结尾没,注意结尾没有有s)是作为专用名词出现的。就是将异常检测程)是作为专用名词出现的。就是将异常检测程序所抛掷的序所抛掷的“带有异常信息的对象带有异常信息的对象”称为称为“异常异常”。而将捕获异常的处理程序称为异常处理程序而将捕获异常的处理程序称为异常处理程序(Exception Handler)。)。在在try复合语句中,可以

380、调用其他函数,在所调用复合语句中,可以调用其他函数,在所调用的函数中检测和抛掷异常,而不是在的函数中检测和抛掷异常,而不是在try复合语句复合语句中直接抛掷异常。这个所调用的函数,仍然是属中直接抛掷异常。这个所调用的函数,仍然是属于这个于这个try模块的,所以这个模块中的模块的,所以这个模块中的catch部分,部分,仍然可以捕获它所抛掷的异常并进行处理。仍然可以捕获它所抛掷的异常并进行处理。2021/6/44972、C+异常处理机制异常处理机制C+处理异常有两个基本的做法:异常的检测和处理是在不同的代码段中进行的。异常的检测和处理是在不同的代码段中进行的。一般的是在一般的是在“try”部分检测

381、异常,部分检测异常,“catch”部分处部分处理异常。理异常。由于异常的检测和处理不是在同一个代码段中由于异常的检测和处理不是在同一个代码段中进行的,在检测异常和处理异常的代码段之间进行的,在检测异常和处理异常的代码段之间需要有一种传递异常信息的机制,在需要有一种传递异常信息的机制,在C+中是中是通过通过“对象对象”来传递异常的。这种对象可以是一来传递异常的。这种对象可以是一种简单的数据(如整数),也可以是系统定义种简单的数据(如整数),也可以是系统定义或用户自定义的类的对象。或用户自定义的类的对象。2021/6/44982021/6/44992021/6/45002、C+异常处理机制异常处理

382、机制阅读这个程序,可以注意以下几点:在在try的复合语句中,调用了函数的复合语句中,调用了函数divide。因此,。因此,尽管尽管divide函数是在函数是在try模块的外面定义的,它仍模块的外面定义的,它仍然是属于然是属于try模块:在模块:在try语句块中运行;语句块中运行;divide函数检测到异常后,抛掷出一个字符串作函数检测到异常后,抛掷出一个字符串作为异常对象,异常的类型就是字符串类型;为异常对象,异常的类型就是字符串类型;catch程序块指定的异常对象类型是程序块指定的异常对象类型是char*,可以,可以捕获字符串异常。捕获异常后的处理方式是通过捕获字符串异常。捕获异常后的处理方

383、式是通过continue语句,跳过本次循环,也不输出结果,语句,跳过本次循环,也不输出结果,直接进入下一次循环,要求用户再输入一对实数。直接进入下一次循环,要求用户再输入一对实数。2021/6/45012、C+异常处理机制异常处理机制2021/6/45022、C+异常处理机制异常处理机制判断:判断:throw抛弃的异常是否与抛弃的异常是否与catch子子句异常类型说明一致。句异常类型说明一致。 try语句块和语句块和catch语句块是一个整体,语句块是一个整体,两者之间不能有其他的语句;两者之间不能有其他的语句; 一个一个try语句块后面可以有多个语句块后面可以有多个catch语句,但是,不可以几个语句,但是,不可以几个try语句块后面语句块后面用一个用一个catch语句。语句。2021/6/4503

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 其它相关文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号