C++程序设计教程.ppt

上传人:cn****1 文档编号:579726734 上传时间:2024-08-27 格式:PPT 页数:360 大小:2.86MB
返回 下载 相关 举报
C++程序设计教程.ppt_第1页
第1页 / 共360页
C++程序设计教程.ppt_第2页
第2页 / 共360页
C++程序设计教程.ppt_第3页
第3页 / 共360页
C++程序设计教程.ppt_第4页
第4页 / 共360页
C++程序设计教程.ppt_第5页
第5页 / 共360页
点击查看更多>>
资源描述

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

1、返回返回 面向对象的程序设计语言面向对象的程序设计语言C+Welcome to learn C+ !讲授:刘韶涛讲授:刘韶涛 副教授副教授E-mail:1返回返回 第一部分第一部分 C+C+语言基础语言基础本部分是学习C+语言的基础,包括以下几个方面:1.C+概述2.结构化程序设计方法与面向对象程序设计方法的各自特点、区别和相互联系。3面向对象的程序设计方法中的有关概念,如类、对象、封装、继承、消息和多态性等。4C+程序的基本组成和框架结构。5掌握C+语言中的基本数据类型、各种运算符、表达式。6C+数据输入流对象cin和输出流对象cout的使用。7程序的3种基本结构8构造数据类型,如数组、结构

2、体、指针等的定义方法、特点和使用方法。9函数的定义、调用及函数调用过程中的参数传递的机理和程序执行流程。10引用的概念及其定义和使用方法。2返回返回 1.1 C+概述概述1.1.1 计算机系统的层次结构计算机系统的层次结构 应用软件 通 处 理 工 用 作 具 软 言 系 系 软件语操裸机 统 统 件计算机系统的层次结构图3返回返回 1.1 C+概述概述1.1.1 计算机系统的层次结构计算机系统的层次结构 任何计算机系统都必须包含硬件和在其上运行的软件。计算机硬件必须有软件的支持才能有效地运转并为人们所利用。计算机硬件系统一般由处理器(控制器和运算器)、存储器、输入设备和输出设备等部分组成。一

3、般来讲,人们认为软件系统由系统软件和应用软件两部分组成。我们从系统层次的角度,可以把软件分为:(1)操作系统(OS,Operating System) 它是计算机软件的核心,是硬件的第一级扩充。在它的控制下,计算机的全部资源,如CPU、内存、外部设备(CRT、打印机,扫描仪、光盘机等)和各种软件资源可以协调一致地工作。它可以有条不紊、高效率地管理和调度计算机地硬件设备和各种软件资源,使它们最大限度地发挥作用。操作系统还要协调控制许多可能“并发”执行的程序段,按照预先确定的控制策略合理地组织系统的工作流程,提高系统的执行效率,保护系统和用户的信息安全。常用的操作系统:MS-DOS,Windows

4、,Unix等。4返回返回 1.1 C+概述概述(2)语言处理系统 其主要的核心部分是程序设计语言的编译系统。程序设计语言是从事计算机的技术人员,特别是软件编写者不可缺少的编程工具,是“驾驶”计算机运行的“方向盘”。 目前世界上经设计和实现的程序设计语言有上千种之多。大致可分为两大类,一类是因计算机中央处理器(CPU)不同而异的汇编语言,另一类是通用的程序设计语言。前者称为低级语言,后者称为高级语言。说汇编语言是一种低级语言,是因为计算机硬件是最低层的,而隶属于语言处理系统的汇编语言最接近于硬件,它是在机器码语言的基础上直接发展起来的一种面向机器的低级语言,它的每一条指令与机器码语言的指令保持着

5、一一对应的关系,可方便地对硬件实现控制和操作,能充分发挥硬件的潜力,且用汇编语言编写的程序与高级语言相比执行速度最快。5返回返回 1.1 C+概述概述 从计算机的根本原理来说,计算机只能理解和执行一系列二进制指令码,即由数字0和1的不同排列组合而成的二进制码对应不同操作的指令,这就是通常所说的“机器码指令”。用上述各 种语言(包括汇编语言在内)编写的程序称为“源程序(Source Program)”,源程序不能直接在计算机上运行,而必须经过语言处理系统进行“翻译”加工,转换成机器码指令后才能执行。常用的语言有:古典语言(Fortran、Pascal、Cobol,Basic等)、人工智能语言(L

6、ISP,PROLOG等)以及现代的语言(C/C+,JAVA,Delphi,Powerbuilder,C#等)。6返回返回 1.1 C+概述概述 关于关于C和和C+C是最靠近机器的通用程序设计语言。在最初设计时是作为一种面向系统软件(操作系统和语言处理系统)的开发语言,即用来代替汇编语言的,但是由于它具有强大的生命力,因而在事务处理、科学计算、工业控制和数据库技术等各个方面都得到了广泛的应用。即使进入到以计算机网络为核心的信息时代,C语言仍然是作为通用的汇编语言使用,用于开发软(件)、硬(件)结合的程序,如实时监控程序、系统控制程序和设备驱动程序等。C+是C的面向对象扩展,是面向对象程序设计语言

7、的一个大众化版本,是当前学习面向对象程序设计方法的首选语言。C+是C的超集,它保留了C的所有组成部分并与其完全兼容,既可以做传统的结构化程序设计,又能进行面向对象程序设计,是当今世界最为流行的面向对象程序设计语言。大大型应用软件开发上,以Windows开发环境为操作平台的C+类库和组件正在迅猛发展,C+即将取代C已是不可抗拒的事实,它的触角几乎已触及到计算机研究和应用的各个领域。完全遵循美国国家标准化组织制定的ANSIC+标准,目前广泛流行在微型计算机上使用的C+产品,有美国Microsoft公司推出的、以Windows开发环境为操作系统平台的VisualC+,还有美国Borland公司开发的

8、C+Builder等。7返回返回 1.1 C+概述概述(3)通用软件通用软件可分为如下几组:(a)数据处理类软件:进行数值计算(行列式、矩阵、复变函数等计算)、统计分析、数学表达式分析计算以及模拟处理的程序等。(b)进行声音、图形、图像和动画等多媒体信息处理的程序。(c)有关自然语言处理、模式识别、神经网络和专家系统等人工智能方面的应用程序。(d)计算机辅助设计与制造(CAD/CAM)、计算机辅助教学(CAI)、计算机辅助分析以及决策支持系统等方面的通用程序。(4)应用软件除通用软件以外的各种应用程序统称为应用软件。当前从事应用软件的开发是各类计算机应用专业技术人员的大舞台,这些技术人员既具有

9、扎实的本专业知识,又掌握了计算机的应用知识,很善于把计算机当作工具来完成本应用领域中的各种任务。应用领域大致可划分为:科学计算,如天文、气象等大型计算任务;办公自动化(OA-OfficeAutomation),如Office 2000;数据库技术领域,如FoxPro、Sybase和Oracle等;工业控制领域,产品如Intouch等。8返回返回 1.1 C+概述概述(5)工具软件是为协助用户更方便地使用计算机完成开发任务而研制,并集多种功能于一体地支程序软件包。如PCTools、FrontPage2000、Cutftp等等。9返回返回 1.2 从面向过程的程序设计到面向对象的程序设计从面向过程

10、的程序设计到面向对象的程序设计1.2.1 传统的结构化程序设计传统的结构化程序设计(Structured Programming-SP)方法方法 1 1使用使用SPSP方法设计程序的步骤方法设计程序的步骤在数据处理过程中,采用的是自顶向下、分而治之的方法,将整个程序按功能划分为几个可独立编程的子过程模块,每一子模块完成指定的子任务,并且提供一个清晰、严格的调用界面,主过程通过调用各子过程完来成全部处理工作 。数据声明数据处理结果输出10返回返回 2 2SPSP方法的特点方法的特点优点:(1)这种程序设计方法力求算法描述准确。(2)对每一子过程模块容易进行程序正确性证明。缺点:(1)这种程序设计

11、方法本质上是面向“过程”的,而“过程”和“操作”又是不稳定和多变的,因此不能直接反映人类求解问题的思路。(2)程序代码可重用性差。程序中除少数标准库函数外,每设计一个程序时,程序员几乎从零做起。即使重用代码,通常也是通过拷贝或编辑重新生成一份。(3)维护程序的一致性困难。该种方法将数据与对数据进行处理的程序代码分离。1.2 从面向过程的程序设计到面向对象的程序设计从面向过程的程序设计到面向对象的程序设计11返回返回 1.2.2面向对象的程序设计(Object-OrientedProgramming-OOP)方法1. 1. 面向对象的有关概念面向对象的有关概念 面向对象的程序设计方法强调直接以问

12、题域(现实世界)中的事物为中心来思考和认识问题,并按照这些事物的本质特征把它们抽象为对象,以作为构成软件系统的基础。( 1 1) 对对 象象 ( ObjectObject) : 每 个 对 象 都 具 有 属 性(Attribute)和方法(Method)这两方面的特征。对象的属性描述了对象的状态和特征,对象的方法说明了对象的行为和功能,并且对象的属性值只应由这个对象的方法来读取和修改,两者结合在一起就构成了对象的完整描述。 1.2 从面向过程的程序设计到面向对象的程序设计从面向过程的程序设计到面向对象的程序设计12返回返回 (2 2)类()类(ClassClass):):具有相似属性和行为的

13、一组对象,就称为类。可见,有了类的概念以后,就可以对具有共同特征的事物进行统一描述。(3 3)封装()封装(EncapsulationEncapsulation):):封装把对象的属性和方法看成了一个密不可分的整体,从而使对象能够完整地描述并对应于一个具体事物。(4 4)继承()继承(InheritanceInheritance):):将客观事物进行归类是一个逐步抽象的过程,反之,将类进行层层分类便是一个概念逐渐细化的过程。在面向对象的程序设计中,允许在已有类的基础上通过增加新特征而派生出新的类,这称为继承。其原有的类称为基类(base class),而新建立的类称为派生类(derived c

14、lass)。1.2 从面向过程的程序设计到面向对象的程序设计从面向过程的程序设计到面向对象的程序设计13返回返回 (5 5)消息()消息(MessageMessage):):在面向对象的程序设计中,由于对象描述了客观实体,它们之间的联系通过对象间的联系来反映。当一个对象需要另外一个对象提供服务时,它向对方发出一个服务请求,而收到请求的对象会响应这个请求并完成指定的服务。这种向对象发出的服务请求就称为消息。(6 6)多态性()多态性(PolymorphismPolymorphism):):多态性是面向对象的另一重要特征。在通过继承而派生出的一系列类中,可能存在一些名称相同,但实现过程和功能不同的

15、方法(Method)。所谓多态性是指当程序中的其他部分发出同样的消息时,按照接收消息对象的不同能够自动执行类中相应的方法。其好处是,用户不必知道某个对象所属的类就可以执行多态行为,从而为程序设计带来更大方便。1.2 从面向过程的程序设计到面向对象的程序设计从面向过程的程序设计到面向对象的程序设计14返回返回 2. 2. 面向对象的程序设计方法(面向对象的程序设计方法(OOPOOP方法)方法)这种方法将设计目标从模拟现实世界的行为转向了模拟现实世界中存在的对象及其各自的行为。在OOP中,将“对象”作为系统中最基本的运行实体,整个程序即由各种不同类型的对象组成,各对象既是一个独立的实体,又可通过消

16、息相互作用,对象中的方法决定要向哪个对象发消息、发什么消息以及收到消息时如何进行处理等。1.2 从面向过程的程序设计到面向对象的程序设计从面向过程的程序设计到面向对象的程序设计方法数据消息消息15返回返回 3 3OOPOOP方法的特点方法的特点(1)OOP以“对象”或“数据”为中心。由于对象自然地反映了应用领域的模块性,因此具有相对稳定性,可以被用作一个组件去构成更复杂的应用,又由于对象一般封装的是某一实际需求的各种成分,因此,某一对象的改变对整个系统几乎没有影响。(2)引入了“类”(class)的概念。类与类以层次结构组织,属于某个类的对象除具有该类所描述的特性外,还具有层次结构中该类上层所

17、有类描述的全部性质,OOP中称这种机制为继承。(3)OOP方法的模块性与继承性,保证了新的应用程序设计可在原有对象的数据类型和功能的基础上通过重用、扩展和细化来进行,而不必从头做起或复制原有代码,这样,大大减少了重新编写新代码的工作量,同时降低了程序设计过程中出错的可能性,达到了事半功倍的效果。1.2 从面向过程的程序设计到面向对象的程序设计从面向过程的程序设计到面向对象的程序设计16返回返回 1.2.3 1.2.3 面面向向对对象象的的程程序序设设计计方方法法与与结结构构化化程程序序设设计计方方法法的比较的比较(1)传统的结构化程序设计方法以过程为中心构造应用程序,数据和处理数据的过程代码是

18、分离的、相互独立的实体,设计出的程序可重用代码少,且当代码量增加时维护数据和代码的一致性困难。(2)面向对象程序设计方法中,对象所具有的封装性和继承性使得代码重用成为可能,并大大减少了程序出错的可能性。(3)面向对象方法吸收了结构化程序设计方法的优点,同时引入了新概念、新机制并建立了比传统方法更高层次的抽象。1.2 从面向过程的程序设计到面向对象的程序设计从面向过程的程序设计到面向对象的程序设计17返回返回 1.3.1 1.3.1 从从C C语言到语言到C+C+语言语言 C语言以其如下独有的特点风靡了全世界:(1)语言简洁、紧凑,使用方便、灵活。C语言只有32个关键字,程序书写形式自由。(2)

19、丰富的运算符和数据类型。(3)可以直接访问内存地址,能进行位操作,使其能够胜任开发操作系统的工作。(4)生成的目标代码质量高,程序运行效率高。(5)可移植性好。1.3 C+1.3 C+程序的基本组成程序的基本组成18返回返回 1.3 C+1.3 C+程序的基本组成程序的基本组成 局限性:(1)数据类型检查机制相对较弱,这使得程序中的一些错误不能在编译阶段被发现。(2)C本身几乎没有支持代码重用的语言结构,因此一个程序员精心设计的程序,很难为其它程序所用。(3)当程序的规模达到一定程度时,程序员很难控制程序的复杂性。19返回返回 1.3 C+1.3 C+程序的基本组成程序的基本组成C+包含了整个

20、C,C是建立C+的基础。C+包括C的全部特征和优点,同时添加了对面向对象编程(OOP)的完全支持。1980年,贝尔实验室的Bjarne Stroustrup开始对C进行改进和扩充。1983年正式命名为C+。在经历了3次C+修订后,1994年制定了ANSI C+ 标准的草案。以后又经过不断完善,成为目前的C+。C+仍在不断发展中。美国微软公司现已推出C#(C Sharp)语言,来代替C+语言。20返回返回 1.3.2 C+程序的结构与基本组成程序的结构与基本组成一个简单的C+程序,是由若干个函数构成的,其中有且仅有一个名称为main的函数存在,下图说明了C+程序的基本框架结构:1.3 C+1.3

21、 C+程序的基本组成程序的基本组成声声明明区区#include:函数声明定义全局变量主主程程序序区区类型main(参数行)程序主体;函函数数定定义义区区函数定义函数主体;21返回返回 1声明区声明区处在程序文件的所有函数的外部。(1)包含头文件:如#includeiostream.h(2)宏定义:如#definePI3.1415926(3)类定义:如classname;/也可以在函数体内(4)结构体定义:如structrecord;(5)函数声明:如voidprint();(6)全局变量声明:如floatH=2.58;(7)条件编译:如#ifdef等。1.3 C+1.3 C+程序的基本组成程序

22、的基本组成22返回返回 2主程序区主程序以main()函数开始,是整个程序运行的入口,该函数中可能包含的内容主要有:(1)局部变量的声明:如:inti=1;(2)函数调用:如:y=sin(x);(3)一般运算:如:a=b+c+d/3;(4)结构控制:如:if(ab)c=a;(5)对象与结构的处理。(6)文件的处理等。1.3 C+1.3 C+程序的基本组成程序的基本组成23返回返回 图2.3 C+函数的组成4 4程序举例程序举例1.3 C+1.3 C+程序的基本组成程序的基本组成函数定义区函数说明intmax(inta,intb)函数体intc;c=a+b;return(c);3函数定义区 程序

23、中除了main函数之外,还可以包含其它的函数,每个函数是由函数说明和函数体两部分构成的。如图2.3所示:24返回返回 1.3 C+1.3 C+程序的基本组成程序的基本组成声声明明区区#includeusingnamespacestd;voidprint();/函数声明主主程程序序区区voidmain()inti;chars80;print();couts;couti;coutsisiyearsold.;函函数数定定义义区区voidprint()printf(printfisalsocanbeusedn);25返回返回 上例程序结构可写为如下程序:【例例2-12-1】一个简单的C+程序。/Thi

24、sisthefirstC+program/*C语言的某些特征仍可沿用*/#includeiostream.hvoidprint();/函数声明voidmain()inti;chars80;1.3 C+1.3 C+程序的基本组成程序的基本组成26返回返回 print();couts;couti;/验证结果coutsisiyearsold.;voidprint()printf(printfisalsocanbeusedn);1.3 C+1.3 C+程序的基本组成程序的基本组成27返回返回 从上例可以看出:(1)C语言中原有的规则和语句在C+中仍可继续使用,但C+又增添了很多新的风格。(2)一个C+

25、的程序是由一到若干个函数构成的,但其中必须有且仅有一个名称为main的函数存在。(3)不管一个程序中有多个函数,只有main函数整个程序运行时的入口,程序运行时从此函数开始执行。但在程序中,main函数所处的位置可以任意。(4)一个C+的函数是由两部分构成的,即函数的说明部分和函数体,函数的说明部分包括了函数的返回值的类型、函数的名称、圆括号、形参及形参的类型说明。函数体由一对大括号括起来,其内容是由若干条语句1.3 C+1.3 C+程序的基本组成程序的基本组成28返回返回 构成,函数体的内容决定了该函数的功能。(5)C+对程序中的名称是大小写“敏感”的,除特殊情况下,应一律小写。(6)程序中

26、的注释:可以用/*/或/(单行注释)对程序中的内容进行注释。二者的区别在于,采用/*/方法时,注释可以写成多行,而采用/方法时,注释只能写成一行,它可单独占一行,也可写在某行程序代码的末尾。(7)数据输出:除了使用printf()函数,还可使用功能更强大、更方便的cout对象进行输出数据。格式如下:cout数据1 数据2 数据n如:上例中的语句couts“is”i变量1变量2变量n如:上例中的语句cins;表示给变量s输入一个值(9) 在分别使用cout和cin进行数据的输出和输入时,需要在程序的开头嵌入”iostream.h”文件。在该头文件中定义了输入输出流对象cout和cin等。(10)

27、 一个C+的源程序文件在存盘时,要以.CPP为文件名后缀,而不是.C。(11)C+程序的开发过程 1.3 C+1.3 C+程序的基本组成程序的基本组成30返回返回 串“yearsold.”2.2 C+2.2 C+程序的基本组成程序的基本组成C+C+程序的开发过程程序的开发过程31返回返回 1.4 C+1.4 C+数据类型、运算符和表达式数据类型、运算符和表达式2.3.1 数据类型数据类型(1)预定义数据类型(基本数据类型)。包括布尔型(bool)、字符型、整型、浮点型、无值型四种,其中浮点型又分为单精度浮点型和双精度浮点型两种。(2)构造数据类型,包括数组、结构体、共用体(联合)、枚举、类等。

28、本节重点介绍C+的基本数据类型,有关构造数据类型将在后面章节进行介绍。32返回返回 2.3.1.1 基本数据类型基本数据类型1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式数据类型数据类型关键字关键字字节数字节数数值范围数值范围布尔型bool1true(非0)或false(0)字符型char1-128127整型int4-21474836482147483647单精度浮点型float4(3.4E-383.4E38)双精度符点型double8(1.7E-3081.7E308无值型void0valueless33返回返回 2.3.1.2 类型修饰符类型修饰符C+还允许在基本数

29、据类型(除void类型外)前加上类型修饰符,来更具体地表示数据类型。C+的类型修饰符包括:signed有符号unsigned无符号short短型long长型 1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式34返回返回 数据类型标识符数据类型标识符字节数字节数数值范围数值范围常量写法举例常量写法举例char1-128127A,0,nsignedchar1-12812756unsignedchar10255100shortint2-3276832767100signedshortint2-3276832767-3456unsignedshortint20655350xff

30、int4-214748364821474836471000signedint4-21474836482147483647-123456unsignedint4042949672950xffff表2.2C+的基本数据类型35返回返回 数据类型标识符数据类型标识符字节数字节数数值范围数值范围常量写法举例常量写法举例longint4-21474836482147483647-123456signedlongint4-21474836482147483647-3246unsignedlongint404294967295123456float4(3.4E-383.4E38)2.35,-53.231,3

31、E-2double8(1.7E-3081.7E308)12.354,-2.5E10longdouble10(1.2E-49321.2E4932)8.5E-300表2.2C+的基本数据类型36返回返回 说明说明:(1)表中带的部分表示是可以省略的,如shortint可以写为shortint或简写为short,二者的含义是相同的。(2)四种修饰符都可以用来修饰整型和字符型。用signed修饰的类型的值可以为正数或负数,用unsigned修饰的类型的值只能为正数。(3)ANSIC和ANSIC+标准中并没有具体规定各种数据类型的“数据长度”,只要求long型的数据长度不短于int型,short型不长于

32、int型。只要遵循标准所给出的这些原则,具体如何实现由各种语言系统自行决定。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式37返回返回 1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式2.3.1.3 常量常量在C+语言中,数据分为常量和变量两大类。由于程序中的数据是有类型的,所以常量和变量都是有类型之分的。常量按照不同的数据类型可以分为:字符型常量、整型常量、浮点型常量,以及字符串常量等。程序是根据程序中常量的书写格式来区分它是哪种类型常量的。38返回返回 1.整型常量整型常量在程序中书写整型常量时,没有小数部分。用户可根据需要分别可以用十进制

33、、八进制和十六进制的形式书写:十十进进制制格格式式 :由数字0至9和正、负号组成,书写时直接写出数字,如:123,-516,+1000等。 八八进进制制格格式式 :以数字0开头的数字(0至7)序列,0111,010007,0177777等。 十十六六进进制制格格式式 :以0x或0X开头的数字(数字0至9、字母a至z)序列,如0x78AC,0xFFFF等。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式39返回返回 2.浮点型常量浮点型常量只能用十进制来表示。可以用小数或指数形式表示(缺省为double)。如:34.5f,.345,1.5e-33.字符型常量字符型常量(1

34、)用一对单引号括起来的一个字符,单引号只是字符与其他部分的分割符,不是字符的一部分,并且,不能用双引号代替单引号。在单引号中的字符不能是单引号或反斜杠。如:a,A,#合法的字符常量,非法的字符常量/可以, “A”不代表字符常量/为字符串常量(2)另一种表示字符常量的方法是使用转义字符。C+规定,采用反斜杠后跟一个字母来代表一个控制字符,具有新的含义。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式40返回返回 C+中常用的转义字符/例转义字符例.cpp转义字符转义字符含义含义ASCII码值(十进制)码值(十进制)a响铃(BEL)7b退格(BS)8n换行(LF)10r回车

35、(CR)13t水平制表(HT)9v垂直制表(VT)11反斜杠92单引号39”双引号340空格符(NULL)0ddd任意字符3位八进制数xhh任意字符2位十六进制数1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式41返回返回 4.4.字符串常量字符串常量 用一对双引号括起来的一个或多个字符的序列称为字符串常量或字符串。字符串以双引号为定界符,双引号不作为字符串的一部分。如: “Hello”, “Good Morning!” ,“I say: “ Goodbye!” 字符串中的字符数称为该字符串的长度,在存储时,系统自动在字符串的末尾加以字符串结束标志,即转义字符 0。/可

36、以“hello0”/串比较的错误方式.cpp5.5.符号常量符号常量 常量也可用一个标识符来代表,称为符号常量。如:#definePRICE30voidmain(void)1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式42返回返回 使用符号常量应注意以下几个方面:(1)它不同于变量,在作用域内其值不能改变和赋值。如:在上例中如再用PRICE=40;这一语句进行赋值则是错误的。(2)符号常量名一般用大写,而变量名用小写,以示区别。6. 程序中常量的表示方法程序中常量的表示方法在程序中的常量有以下三种表示方法:(1)在程序中直接写入常量如 : -200, 3.4E-10,

37、A, 1, 0x120, 045, 5.35,1000linti;chars;floatf;i=20;s=a;f=2.0F;1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式43返回返回 (2)利用#define定义宏常量一般格式:#define宏名常数如:#definePI3.14s=2*PI*r;(3)利用const定义正规常数一般格式:const数据类型标识符常数名=常量值;说明:const必须放在被修饰类型符和类型名前面数据类型是一个可选项,用来指定常数值的数据类型,如果省略了该数据类型,那么编译程序认为它是int类型1.3 C+1.3 C+数据类型、运算符和表达

38、式数据类型、运算符和表达式44返回返回 如:constinta=10;表示定义了一个初始值为10的整型常量,它在程序中不可改变,但可用于表达式的计算中./const面试题1.cppconst面试题2.cpp2.3.1.4 变量变量1变量的概念变量的概念及特点及特点每一变量就相当于一个容器,对应着计算机内存中的某一块存储单元,用于存储程序中的数据。变量的值具有以下两个特点:(1)“一充即无”:即将一个新数据存放到一个变量中时,该变量中原来的值消失,变量的值变成了新值。如:执行完语句inti;i=10;i=20;后i的值为20,而不是10。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、

39、运算符和表达式45返回返回 (2)“取之不尽”:可将某个变量的值与程序中的其它数据进行各种运算,在运算过程中,如果没有改变该变量的值时,那么,不管用该变量的值进行多少次运算,其值始终保持不变。如:语句inti,j,k;i=10;j=i+10;k=i+j*5;其中,i的值可无限制地多次使用,但它的值始终保持值10,因为在程序中没有改变变量i的值。2定义变量定义变量程序中的每一变量,都要先定义,后使用。定义变量的一般有以下三种格式:数据类型标识符变量名;数据类型标识符变量名=初始化值;1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式46返回返回 数据类型标识符变量名1=初始

40、值1,变量名2=初始值2,;如:chara; /定义字符型变量ainti=1000;/定义整型变量i,i的初始值为1000;floata=2.0,b=3.0,c;/定义浮点型变量a、b、c,且a、b的初始值分别为2、3。变量名是每个变量的名称,其命名遵循以下规则:(1)由字母、数字和下划线(_)三类符号排列组合形成,且开头字符必须是字母或下划线。(2)名称中字符的最大个数是31个。(3)C+中区分变量名的大小写。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式47返回返回 (4)变量名不能和C+中的关键字同名,也不能和用户编制的函数或C+库函数同名。如:int,doub

41、le或static都不能作为变量名。(5)变量名尽量做到“见名知意”。3定义变量的位置定义变量的位置在程序中的不同位置采用不同的变量定义方式,决定了该变量具有不同的特点。变量的定义一般可有以下三种位置:(1)在函数体内部在函数体内部定义的变量称为局部变量,这种局部变量只在进入定义它的函数体时起作用,离开该函数体后该变量就消失(被释放),即不再起作用。因此,不同函数体内部可以定义相同名称的变量,而互不干扰。如:1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式48返回返回 voidfunc1(void)inty;y=2;voidfunc2(void)inty;y=-100;

42、在本例中,函数func1和func2的函数体内部都分别定义了变量y,但它们都只能在各自的函数体内起作用,都是局部变量。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式49返回返回 (2)形式参数)形式参数当定义一个有参函数时,函数名后面括号内的变量,统称为形式参数。如:intis_in(char*a,charb)while(*a)if(*a=b)return1;elsea+;return0;本例中,函数名is_in后面括号内的变量a和b是该函数的形式参数,它们都只能在该函数体内起作用,是该函数的局部变量。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和

43、表达式50返回返回 (3)全全局局变变量量:在所有函数体外部定义的变量,其作用范围是整个程序,并在整个程序运行期间有效。如:#include“stdio.h”intcount;/定义count变量是全局变量voidfunc1(void);voidfunc2(void);intmain()count=10;func1();return0;1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式51返回返回 voidfunc1(void)inttemp;temp=count;func2();printf(“countis%d”,count);/输出10voidfunc2(void)

44、intcount;for(count=1;count10;count+)putchar(.);/赋值语句面试题2.cpp1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式52返回返回 1.3.2 运算符和表达式运算符和表达式程序中对数据进行的各种运算是由运算符来决定的,不同运算符的运算方法和特点是不同的,从此可以看出,一个运算式子中要涉及到数据及运算符,而运算符是对数据进行指定操作,并产生新值的特殊符号。2.3.2.1 算术运算符和算术表达式算术运算符和算术表达式算术运算符就是对数据进行算术运算,如:加、减、乘、除等,是在程序中使用最多的一种运算符,C+的算术运算符如表2

45、.4所示。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式53返回返回 运算符运算符功能功能数据类型数据类型例子例子-负号数值x=-y;+加数值z=x+y;-减数值z=x-y;*乘数值z=x*y/除数值z=x/y;%求余整数z=x%y+自加数值z+或+z表2.4C+的算术运算符-自减数值z-或-z算术表达式是指由算术运算符、括号将常量、变量、函数、圆括号等连接形成的一个有意义的式子。如:54返回返回 (1+x)/(3*x)(2*x-3)*x+2)*x)-53.14*sqrt(r)b*b-4.0*a*c注意:(1)表达式中的括号不管有多少层,一律使用圆括号。(2)在将一个

46、数学上的运算式子写成对应的C+的表达式时,要注意进行必要的转换。乘号不能省略。数学表达式中出现的数学运算函数要用C+提供的对应的数学运算库函数来代替。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式55返回返回 要特别注意表达式中两个整型数相除的情况。如:有一数学表达式为2/3(f-32),要写成对应的C+的表达式时,正确地写法应写2.0/3.0*(f-32)。而不是2/3*(f-32)(5/2得到结果2,5.0/2.0得到结果2.5)2.3.2.2 赋值运算符和赋值表达式赋值运算符和赋值表达式赋值运算符的功能将某个数据的值赋给某个变量。赋值运算符的用法格式:变量名赋值

47、运算符常量、变量或表达式说明:(1)被赋值的目标,即赋值运算符左边的量必须是变量,而不能是常量或表达式。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式56返回返回 (2)C+中的赋值运算符如表2.5所示。(3)要注意区分赋值运算符“=”与数学上的“等号”间的区别,如:intx,y;/定义变量x,y为int类型变量x=10;/将变量x赋成值10赋值运算符赋值运算符例子例子等价形式等价形式=x=x+yx=x+y+=x+=y+zx=x+(y+z)-=x-=y+zx=x-(y+z)*=x*=y+zx=x*(y+z)/=x/=y+zx=x/(y+z)%=x%=y+zx=x%(y

48、+z)1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式57返回返回 x=x+20;/将x的值在原值(10)的基础上再加上值20后(结果为30)赋给变量xy-=x+5;/等价于y=y-(x+5)x%=y+10;/等价于x=x%(y+10)(4)前增/减运算是变量的值先自增1或自减1,然后以该变量自增或自减后的值参加其它运算;后增/减运算是该变量先以原来的值参加其它运算,然后再自增1或自减1;增减量运算符只能用于变量,不能用于常量和表达式。如:7+;(i+j)+;/error1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式58返回返回 (5)对表达式

49、x+y的理解:是(x+)+y还是x+(+y)?C+规定,处理时从左至右取尽可能多的“+”或“-”号字符组成一个运算符,将解释为(x+)+y。编程者最好采用便于阅读和理解的写法,写成(x+)+y的形式。/i+面试题2.cppi+面试题3.cppi+面试题4.cpp(6)在ANSIC中,增量运算符“+”和减量运算符“-”只能用于整型量,而在ANSIC+中,这两个运算符对整型和浮点型均可使用。2.3.2.3 sizeof运算符运算符sizeof运算符功能是求某一数据类型或某一变量在内存中所占空间的字节数。其使用的一般形式:sizeof(变量名或数据类型)或sizeof变量名或数据类型如:1.3 C+

50、1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式59返回返回 #includevoidmain()shortintaShort;intanInt;longaLong;charaChar;floataReal;coutdatatypetmemoryused(bytes);coutnshortinttsizeof(aShort);coutnintegertsizeof(anInt);coutnLongintegertsizeof(aLong);coutncharachartsizeof(aChar);coutnfloattsizeof(aReal);1.3 C+1.3 C+数据类型、运

51、算符和表达式数据类型、运算符和表达式60返回返回 其输出结果为:datatypememoryused(bytes)shortint2integer4Longinteger4charachar1float4/sizeof面试题1.cpp2.3.2.4 关系运算符和关系表达式关系运算符和关系表达式关系运算符就是对两个量之间进行比较的运算符,如表2.6所示。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式61返回返回 由关系运算符将两个表达式连接形成的运算式子是关系表达式,一个关系表达式的值是一个逻辑值,当为真时,值为1,为假时,值为0。如:假设a=1,b=20,c=3,则a

52、b表达式成立,其值为1b=c表达式不成立,其值为0(a+b)!=c表达式成立,其值为1关系运算符关系运算符含义含义例子例子10=小于或等于(x+y)*2大于x+yz=大于或等于x-y=a*b+2=等于x+y=a+b!=不等于x-y!=01.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式62返回返回 注意:在对两个表达式的值进行是否相等的比较时,要用运算符“=”,而不能写成“=”。2.3.2.5 逻辑运算符和逻辑表达式逻辑运算符和逻辑表达式逻辑运算符是对两个逻辑量间进行运算的运算符,如表2.7所示。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式逻辑

53、运算符逻辑运算符含义含义例子例子!逻辑非!(x10)&逻辑与(i1)&(ic)的值为1(真)。(2)在逻辑表达式的求值过程中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的值时,才执行该运算符。a&b&c只有a为真时,才需要判别b的值,只有a和b的值都为真时才需要判别c的值。如:inti=10;则表达式i&(i=0)&(+i)的值为0(假),该表达式运算结束后,变量i的值为0,而不是1。/i+面试题5.cpp1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式65返回返回 a|b|c只要a为真,就不必须判断b和c;只有a为假,才判别b;a和b

54、都为假才判别c。如:inti=1,j;则表达式i+|i+|i+的值为1(真),运算结束后,变量i的值为2,而不是4。对于数学上的表示多个数据间进行比较的表达式,在C或C+中要拆写成多个条件并用逻辑运算符连接形成一个逻辑表达式。如:在数学上,要表示一个变量a的值处于-1和-9之间时,可以用-9a-9&a-1,而不能写成-9a-1。因为,假设变量a当前的值为-5,它的值确实处在-1和-9之间,但在C+语言中求-9a-1时,从左向右进行计算,先计算-9a,得1(真),此时该表达式可简化为1-9&ab?a:b的值为4。/i+面试题1.cpp2.3.2.7 位运算符位运算符1位运算符及其运算规则位运算符

55、及其运算规则所谓位运算符是指能进行二进制位运算的运算符。C+提供的位运算符如表2.9所示。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式67返回返回 位运算的运算规则为:(1)按位与&:两个运算量相应的位都是1,则该位的结果值为1,否则为0;(2)按位或|:两个运算量相应的位只要有一个是1,则该位的结果值为1,否则为0;运算符含义例子&按位与i&128|按位或j|64按位异或j12按位取反j按位左移i按位右移j21.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式68返回返回 (3)按位异或:两个运算量相应的位不同,则该位的结果值为1,否则为0;(

56、4)按位取反:将运算量的每一位取反。(5)按位左移:将操作数中的每一位向右移动指定的位数,移出的位被舍弃,空出的位补0或补符号位。如:a=5,b=6,则:a000001010000010100000101b&0000011000000110000001100000011000000100000001110000001111111001即:a&b=4,a|b=7,ab=3,b=-7(-7的补码是11111001)1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式69返回返回 2复合位运算符复合位运算符位运算符与赋值运算符结合可以形成复合位运算符,如表2.10所示。/赋值语句

57、面试题1.cpp2.3.2.8 强制类型转换运算符强制类型转换运算符该运算符的功能是将某一数据从一种数据类型向另一运算符例子等价形式&=x&=y+zx=x&(y+z)|=x|=x+2x=x|(x+2)=x=yx=xy=x=y+zx=x=x=y+zx=x(y+z)1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式70返回返回 种数据类型进行转换。其使用的一般形式:数据类型标识符(表达式)(数据类型标识符)表达式如:inti=2;floata,b;a=float(i);/将变量i的类型强制转换为浮点型,并将/其值赋给变量a,C不允许这样写(编译错误)。b=(float)i;/

58、将变量i的类型强制转换为浮点型,并将/其值赋给变量b,但变量i的值没变!关于自动(隐式(自动(隐式(implicit)类型)类型转换类型)类型转换:这种类型的转换是在执行表达式中的运算符操作时,自动进行的一种转换。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式71返回返回 低高longdouble高intunsignedlongunsignedlongdouble|short,charfloat低数据类型的转换方向数据类型的转换方向说明:水水平平方方向向的的箭箭头头表示运算的变量为不同的数据类型时的转换的方向。如一个int型和一个float型数据进行运算时,由于flo

59、at型首先转换成double型,因此把int的数据也转换成double型,然后再运算,计算结果也是double型。这里的箭头只表示数据类型级别的高低,不是指数据实际转换的步骤,不能把int型转换成double型理解为int型先转换成unsigned,再转换为long型,再转换成unsignedlong型,最后才转换成double型,实际上是把int型数据直接转换成double型。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式72返回返回 纵向箭头表示必定的类型转换。如字符型必定先转换成整数型,short型也必定转换为int型。如两个float型数据进行算术运算时,为了

60、提高运算精度,先都转换成double型后再进行运算。当不同数据类型的变量同时出现在一个表达式时,将实现“隐式类型转换”。它是在数据运算过程中自动进行的类型转换,即把它们转变成同一类型的变量再进行运算。在赋值语句中,当左值和右值的数据类型不同时,首先将右值类型自动转换成左值的类型(向左看齐),然后再赋值给左值。/类型转换面试题.cpp1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式73返回返回 2.3.2.9 逗号运算符逗号运算符逗号运算符的运算优先级是最低的。一般形式为:表达式1,表达式2,表达式N在计算逗号表达式的值时,按从左至右的顺序依次分别计算各个表达式的值,而整

61、个逗号表达式的值和类型是由最右边的表达式决定。如:有语句inta=3,b=4;则表达式a+,b+,a+b的值为9。再如:设有inti;则表达式i=1,i+=2?i+1:i+4的值为6。2.3.2.10 运算符的优先级与结合性运算符的优先级与结合性每个运算符都有自己优先级和结合性。当一个表达式中包含多个运算符时,要确定运算的结果,必须首先确定运算的先后顺序,即运算符的优先级和结合性。C+中运算符的优先级和结合性如表2.11所示。1.3 C+1.3 C+数据类型、运算符和表达式数据类型、运算符和表达式74返回返回 优先级运算符结合性1():(作用域运算符)-.(成员访问符).*-*(成员指针选择符

62、)自左至右2!+-+-(取正负)*&(类型)sizeofnewdelete自右至左3*/%自左至右4+-(加减)自左至右5(左移位,右移位)自左至右6=自左至右7=!=自左至右8&自左至右9自左至右10|自左至右11&自左至右12|自左至右13?:自右至左14=+=-=*=/=%=&=|=自右至左15,自左至右表2.11C+中运算符的优先级和结合性75返回返回 1.4 数据的输入与输出数据的输入与输出在C+语言中,数据的输入和结果的输出是分别使用系统所提供的输入流对象cin和输出流对象cout来完成的。在使用过程中,只要在程序的开头嵌入相应的头文件“iostream.h”即可。1.4.1 数据

63、的输出数据的输出cout输出流对象输出数据的语句格式为:cout数据1数据2数据n;说明:(1)cout是系统预定义的一个标准输出设备(一般代表显示器);“”是输出操作符(插入符),用于向cout输出流中插入数据。(2)cout的作用是向标准输出设备上输出数据,被输出的数据可以是常量、已有值的变量或是一个表达式。76返回返回 如:#include#includevoidmain()floata=3,b=4;coutTheresultis:;coutsqrt(a*a+b*b);该程序的输出结果为:Theresultis:5(3)可以在cout输出流中插入C+中的转义字符。如:couttheval

64、ueofa:n;couta;2.4 数据的输入与输出数据的输入与输出77返回返回 表示输出完字符串Inputthevalueofa:后,在下一行输出变量a的值。(4)可以将多个被输出的数据写在一个cout中,各输出项间用“”操作符隔开即可,但但要要注注意意cout首首先先按按从从右右向向左左的的顺顺序序计计算算出出各各输输出出项项的的值值,然然后后再再输输出出各各项项的的值值。如:coutvalueofa:avalueofb:bTheresultis:sqrt(a*a+b*b);再如:设变量i的值为10,则couti,i+,i+;的输出结果为:12,11,10(5)一个cout语句也可拆成若干

65、行书写,但注意语句结束符“;”只能写在最后一行上。如:对于上面的语句也可写成如下形式:2.4 数据的输入与输出数据的输入与输出78返回返回 coutvalueofa:/注意行末无分号avalueofb:bTheresultis:sqrt(a*a+b*b);/在此处书写分号(6)在cout中,实现输出数据换行功能的方法:既可使用转义字符“n”,也可使用表示行结束的流操作子endl。如:coutThisisfirstLine.nThisissecondline.;上面语句可等价地写为:coutThisisfirstLine.endlThisissecondline.;2.4 数据的输入与输出数据的

66、输入与输出79返回返回 (7)在cout中还可以使用流控制符控制数据的输出格式,但使用这些流控制符时,要在程序的头上嵌入头文件#include。常用的流控制符及其功能如表2.12所示。表2.12I/O流的常用控制符2.4 数据的输入与输出数据的输入与输出控制符功能dec十进制数输出hex十六进制数输出oct八进制数输出setfill(c)在给定的输出域宽度内填充字符csetprecision(n)设显示小数精度为n位setw(n)设域宽为n个字符setiosflags(ios:fixed)固定的浮点显示80返回返回 2.4 数据的输入与输出数据的输入与输出setiosflags(ios:sci

67、entific)指数显示setiosflags(ios:left)左对齐setiosflags(ios:right)右对齐setiosflags(ios:skipws)忽略前导空白setiosflags(ios:uppercase)十六进制数大写输出setiosflags(ios:lowercase)十六进制数小写输出setiosflags(ios:showbase)按十六八进制输出数据时,前面显示前导符0x0;81返回返回 2.4 数据的输入与输出数据的输入与输出设置域宽:所谓域宽就是被输出数据所占的输出宽度(单位是字符数)。设置域宽可以使用流控制符setw(n)和cout的方法cout.w

68、idth(n)其中n为正整数,表示域宽。但是,cout.width(n)和和setw(n)二者都只对下一个被输出的数据有作用,若一二者都只对下一个被输出的数据有作用,若一个输出语句内有多个被输出的数据,而要保持一定格个输出语句内有多个被输出的数据,而要保持一定格式域宽时,需要在每一输出数据前加上式域宽时,需要在每一输出数据前加上cout.width(n)或或setw(n)。此外,当参数n的值比实际被输出数据的宽度大时,则在给定的域宽内,数据靠右输出,不足部分自动填充空格符;若被输出数据的实际宽度比n值大时,则数据所占的实际位数输出数据,设置域宽的参数n不再起作用。82返回返回 【例例2-2】c

69、out流控制符setw的使用。#include#includevoidmain()inta=21,b=999;coutsetw(3)asetw(4)asetw(5)aendl;coutsetw(3)bsetw(4)bsetw(5)bendl;coutsetw(3)a+bsetw(4)a+bsetw(5)a+bendl;其输出结果是:212121/程序中第一个cout的输出结果999999999/程序中第二个cout的输出结果102010201020/程序中第三个cout的输出结果2.4 数据的输入与输出数据的输入与输出83返回返回 设置域内填充字符:在默认情况下,当被输出的数据未占满域宽时,会

70、自动在域内靠左边填充相应个数的空格符。但我们也可以设置在域内填充其他的字符,方法是利用cout的fill方法cout.fill(c)或setfill(c)。cout.fill(c)和和 setfill(c)可以对所有被输出的数据起作用可以对所有被输出的数据起作用。【例例2-3】在例2-2的基础上增加域内填充字符的功能。#include“iostream.h”#include“iomanip.h”voidmain()inta=21,b=999;cout.fill(#);/设置域内填充字符为#字符coutsetw(3)asetw(4)asetw(5)aendl;2.4 数据的输入与输出数据的输入与

71、输出84返回返回 coutsetw(3)bsetw(4)bsetw(5)bendl;cout.fill(%);/将域内填充字符改为%字符coutsetw(3)a+bsetw(4)a+bsetw(5)a+bendl;其输出结果是:#21#21#21/程序中第一个cout的输出结果,未占满域宽的部分填充#字符。999#999#999/程序中第二个cout的输出结果10201020%1020/程序中第三个cout的输出结果,未占满域宽的部分填充%字符。2.4 数据的输入与输出数据的输入与输出85返回返回 当采用流控制符设置填充字符时,上面程序代码也可等价地改为:#include#includevoi

72、dmain()inta=21,b=999;coutsetw(3)setfill(#)asetw(4)asetw(5)aendl;coutsetw(3)bsetw(4)bsetw(5)bendl;coutsetw(3)setfill(%)a+bsetw(4)a+bsetw(5)a+bendl;2.4 数据的输入与输出数据的输入与输出86返回返回 设置输出数据的进位计数制:在默认情况下,被输出的数据按十进制格式输出。但可以使用流控制符hex和oct控制数据的输出格式为十六进制和八进制,一一旦旦设设置置成成某某种种进进位位计计数数制制后后,数数据据的的输输出出就就以以该该种种数数制制为为主主,可可利

73、利用用流流控制控制符符dec将数制重新成十进制将数制重新成十进制。【例例2-4】在例2-2的基础上增加域内填充字符的功能。#include#includevoidmain()inta=21,b=999;/设置以十六制格式输出数据2.4 数据的输入与输出数据的输入与输出87返回返回 coutsetw(3)setfill(#)hexasetw(4)asetw(5)aendl;coutsetw(3)bsetw(4)bsetw(5)bendl;coutsetw(3)setfill(%)a+bsetw(4)a+bsetw(5)a+bendl;/设置以八制格式输出数据coutsetw(3)setfill(

74、#)octasetw(4)asetw(5)aendl;coutsetw(3)bsetw(4)bsetw(5)bendl;coutsetw(3)setfill(%)a+bsetw(4)a+bsetw(5)a+bendl;/设置以十制格式输出数据coutsetw(3)setfill(#)decasetw(4)asetw(5)aendl;coutsetw(3)bsetw(4)bsetw(5)bendl;coutsetw(3)setfill(%)a+bsetw(4)a+bsetw(5)a+bendl;2.4 数据的输入与输出数据的输入与输出88返回返回 程序的输出结果为:#15#15#15/以十六进制

75、格式输出数据3e7#3e7#3e73fc%3fc%3fc#25#25#25/以八进制格式输出数据17471747#174717741774%1774#21#21#21/以十进制格式输出数据999#999#99910201020%10202.4 数据的输入与输出数据的输入与输出89返回返回 设置浮点数的输出格式:对于浮点数,既可以用小数格式输出,也可以用指数格式输出。这可以分别通过setiosflags(ios:fixed)和setiosflags(ios:scientific)来控制。【例例2-5】已知圆的半径r=6.779,计算并输出圆的周长和面积,要求分别用指数和小数两种格式输出。#inc

76、lude#includevoidmain()constdoublepi=3.14159;doubler=6.779,c,s;c=2.0*pi*r;/计算圆的周长s=pi*r*r;/计算圆的面积2.4 数据的输入与输出数据的输入与输出90返回返回 /以指数格式输出圆的面积和周长cout圆的周长(指数)为:setiosflags(ios:scientific)cendl;cout圆的面积(指数)为:sendl;/以小数输出圆的面积和周长cout圆的周长(小数)为:setiosflags(ios:fixed)cendl;cout圆的面积(小数)为:setiosflags(ios:fixed)s变量名

77、1变量名2变量名n;说明:(1)cin是系统预定义的一个标准输入设备(2)cin的功能是:当程序在运行过程中执行到cin时,程序会暂停执行并等待用户从键盘输入相应数目的数据,用户输入完数据并回车后,cin从输入流中取得相应的数据并传送给其后的变量中(提取符)。(3)“”操作符后除了变量名外不得有其他数字、字符串或字符,否则系统会报错。2.4 数据的输入与输出数据的输入与输出92返回返回 如:cinx=x;/错误,因含有字符串x=cinxx;/错误,因含有字符x=cinx10;/错误,因含有常量10(4)cin后面所跟的变量可为任何数据类型,若变量为整型数据类型,则在程序运行过程中从键盘输入数据

78、时,可分别按十进制、八进制或十六进制输入该整数。但要注意:当按十进制格式输入整数时,可直接输入数据本身即可;若以十六进制输入整数时,数据前要冠以0x或0X;若按八进制格式输入整数时,数据前要冠以数字0,。若cin后面的变量为浮点类型(单精度或双精度)时,可分别按小数或指数的格式表示该浮点数。若cin后面的变量为字符类型时,可直接输入字符数据而不能在字符的两端加单引号。2.4 数据的输入与输出数据的输入与输出93返回返回 (5)当程序中用cin输入数据时,最好在该语句之前用cout输出一个需要输入数据的提示信息,以正确引导和提示用户输入正确的数据。如:coutx;(6)当一个cin后面同时跟有多

79、个变量时,则用户在输入数据时的个数应与变量的个数相同,各数据之前用一个或多个空格隔开,输入完后按回车键;或者,每输入一个数据按回车键也可。如对于以下程序段:intx;doublea;charc1;coutxac1;cout整数:x浮点数:a字符:b?a:b;cout“HelloC+”endl;等等。2.5 C+的控制语句的控制语句96返回返回 2. 空语句空语句仅由单个分号构成的语句,即;称为空语句。空语句不进行任何操作。该语句被用在从语法上需要一条语句,但实际上却又不进行任何操作的地方。3.复合语句复合语句复合语句是用一对花括号括起来的语句块。复合语句在语法上等效于一个单一语句。使用复合语句

80、应注意:(1)花括号必须配对使用;(2)花括号外不要加分号。2.5 C+的控制语句的控制语句97返回返回 2.5.2 C+程序的三种基本结构程序的三种基本结构在程序设计中,语句可以按照结构化程序设计的思想构成三种基本结构,它们分别是顺序结构、分支结构和循环结构,如图2.5所示。顺序结构分支结构循环结构图2.5 程序的三种基本结构2.5 C+的控制语句的控制语句语句A语句B条件P语句A语句B真假条件P语句A98返回返回 1顺序结构顺序结构程序按照语句的书写顺序依次执行,语句在前的先执行,语句在后的后执行,只能满足设计简单程序的要求。2. 分支结构分支结构在分支结构中,程序根据判断条件是否成立,来

81、选择执行不同的程序段。也就是说,这种程序结构,能有选择地执行程序中的不同程序段。3. 循环结构循环结构在循环结构中,程序根据判断条件是否成立,来决定是否重复执行某个程序段。程序的执行流程和顺序是由程序中的控制语句来完成的,而控制流程的主要方式是分支和循环。2.5 C+的控制语句的控制语句99返回返回 2.5.3 if 语句语句if语句是最常用的一种分支语句,也称为条件语句。if语句有三种形式:单分支if语句、双分支if语句和多分支if语句,如图2.6所示。单分支if语句双分支if语句2.5 C+的控制语句的控制语句真假表达式语句真假表达式语句1语句2100返回返回 多分支if语句2.5.3.1

82、 单分支单分支if 语句语句if(表达式)语句真真2.5 C+的控制语句的控制语句真假假假表达式1表达式2语句1语句2语句3语句4表达式2101返回返回 其执行过程为:先计算关键字if后面的表达式的值,若为真,则执行if后的“语句”部分,否则跳过该“语句”部分。不管是否执行“语句”部分,最后都要接着“语句”部分的后面,继续执行程序的其它部分。注意:(1)括号不能省略。(2)在if(表达式)后不能加分号“;”。(3)关键字if的后面的表达式可以是任意的表达式,只要表达式的值为非0,即当真值处理,否则当假值处理。(4)if语句的内嵌语句可以是单一语句,也可以是复合语句。(5)尽量使if语句的内嵌语

83、句比if语句缩进,这是良好编程书写风格。2.5 C+的控制语句的控制语句102返回返回 如:intx=0,y=2;if(x=0)y+;coutxy;运算结束后,变量y的值为2,而不是3,变量x的值为0。2.5.3.2 双分支双分支if语句语句双分支if语句的一般格式为:if(表达式)语句块1else语句块22.5 C+的控制语句的控制语句103返回返回 其执行过程为:先判断表达式的值,若为真,则执行语句块1,否则执行语句块2。不管程序执行语句块1还是执行语句块2,最后都要跳到语句块2的后面接着执行程序中后面的语句。注意:(1)语句块1、语句块2既可以是单一语句也可以是用括起来的复合语句。(2)

84、else子句必须与子句必须与if子句配对使用,不能单独使用子句配对使用,不能单独使用。(3)else子子句句必必须须处处在在if子子句句的的后后面面,且且else语语句句总总是是和和离它最近的前面未配对的离它最近的前面未配对的if语句配对语句配对。【例例2-6】输入一个年号,判断是否为闰年,如果是则输出“yes”,否则输出“Not”。分析:只要满足下列两个条件之一者,即是闰年。2.5 C+的控制语句的控制语句104返回返回 年号能被4整除,但要排除同时能被100整除;年号能被400整除。#includevoidmain()inty;couty;if(y%4=0&y%100!=0)|(y%400

85、=0)coutYes;elsecoutNot;coutscore80为良,80score70为中等,70score60为及格,score60为不及格。#includevoidmain()floatscore;coutscore;if(score=90)cout=80)cout=70)cout=60)coutPass!;elsecoutscore80为良,80score70为中等,70score60为及格,score60为不及格。#includevoidmain()2.5 C+的控制语句的控制语句110返回返回 floatscore;inta;coutscore;a=score/10;switc

86、h(a)case10:case9:coutExcellent!;break;case8:coutGood!;break;case7:coutRight!;break;case6:coutPass!;break;default:coutFailed!;2.5 C+的控制语句的控制语句111返回返回 说明:常常数数1常常数数n必必须须互互不不相相同同,且每一常数后面要有冒号“:”;各case子句和default子句的次序可任意;语句1语句n+1可以为复合语句;在switch语句中出现的break语语句句并并不不是是必必需需的的,这要根据程序的需要来决定。在此break语句的作用是跳出switch语

87、句;各case子句后面必须是常数,而不能是变量或表达式2.5.5 循环语句循环语句C+提供了三种循环结构:while循环语句、do-while循环语句和for循环语句。2.5 C+的控制语句的控制语句112返回返回 2.5.5.1 while循环语句循环语句while语句的一般形为:while(表达式)循环体语句该语句的执行过程:首先判断while后面的表达式的值,若表达式的值为真,则执行while的内嵌语句(即循环体)一次;然后重复以上过程,直到表达式的值为假时,才退出循环,接着执行循环体语句后面的其它程序语句。【例例2-9】求2.5 C+的控制语句的控制语句113返回返回 #include

88、voidmain()inti,n;n=0;i=1;while(i=100)n=n+i;i+;coutn=nendl;2.5.5.2 do-while 循环语句循环语句do-while语句的一般形式为:2.5 C+的控制语句的控制语句114返回返回 do循环体语句while(表达式);该语句的执行过程:首先执行do-while的内嵌语句(循环体语句)一次,然后再判断while后面的表达式的值,若表达式的值为真,则重复执行do-while的内嵌语句,如此反复,直到表达式的值为假时,循环结束,执行while后面的语句。【例例2-10】求#includevoidmain()2.5 C+的控制语句的控制

89、语句115返回返回 inti,n;n=0;i=1;don=n+i;i+;while(i=100);coutn=nendl;说明:在循环体相同的情况下,while语句和do-while语句的功能基本相同。二者的区别在于:当循环条件一开始就为假时,do-while语句中的循环体至少会被执行一次,而while语句则一次都不执行。2.5 C+的控制语句的控制语句116返回返回 2.5.5.3 for循环语句循环语句for循环语句的一般格式为:for(表达式1;表达式2;表达式3)循环体语句该语句的执行过程是:执行for后面的表达式1;执行表达式2,若表达式2的值为真,则执行for语句的内嵌语句(即循环

90、体语句),然后执行第步,若为假,则循环结束,执行第步;执行表达式3;返回继续执行第步;循环结束,执行for语句的循环体下面的语句。2.5 C+的控制语句的控制语句117返回返回 【例例2-11】求。用for语句实现循环。#includevoidmain()inti,n;n=0;for(i=1;i=100;i+)n=n+i;coutn=nendl;2.5.5.4 循环嵌套循环嵌套在一个循环的循环体中又包含另一个循环语句,称为循环嵌套。C+的三种循环语句可以相互嵌套,构成循环2.5 C+的控制语句的控制语句118返回返回 嵌套。以下几种都是合法的循环嵌套:(1)for(;)for(;)(2)whi

91、le()for(;)dowhile();2.5 C+的控制语句的控制语句119返回返回 (3)dofor(;)while();同样,if语句和switch语句也可以与这三种语句嵌套使用。注意:(1)循环嵌套时,外层循环和内层循环间是包含关系,即内层循环必须被完全包含在外层循环中,不得不得交叉交叉。(2)当程序中出现循环嵌套时,这时,程序每执行一次外层循环,则其内层循环必须循环所有的次数(即内层2.5 C+的控制语句的控制语句120返回返回 循环结束)后,才能进入到外层循环的下一次循环。2.5.5.5 限定转向语句限定转向语句C+提供了跳转语句break和继续语句continue。1. brea

92、k语句语句break语句的一般形式为:break;该语句只能用于两种情况:(1)用在switch结构中,当某个case子句执行完后,使用break语句跳出switch结构。(2)用在循环结构中,用break语句来结束循环。如果在嵌套循环中,break语句只能结束其所在的那层循环语句只能结束其所在的那层循环。2.5 C+的控制语句的控制语句121返回返回 【例例2-12】任意输入若干个整数(不多于50个),计算已输入整数之和,直到输入了负数为止。#includevoidmain()inti,n,sum;sum=0;for(i=0;i=50;i+)coutn;if(n0)break;2.5 C+的

93、控制语句的控制语句122返回返回 sum+=n;coutsum=sumendl;2.continue语句语句continue语句的一般形式为:continue;该语句只能用在循环结构中。当在循环结构中遇到continue语句时,则跳过continue语句后的其他语句结束本次循环,并转去判断循环控制条件,以决定是否进行下一次循环。【例例2-13】输出0100之间所有不能被3整除的数。2.5 C+的控制语句的控制语句123返回返回 #includevoidmain()inti;for(i=0;i=100;i+)if(i%3=0)continue;coutiendl;2.5.5.6 三种循环的比较三

94、种循环的比较(1)三种循环可以相互代替;且都可以使用break和continue语句限定循环转向;(2)while语句和for语句是先判断条件,后执行循环体,而do-while语句是先执行循环体,后判断条件;2.5 C+的控制语句的控制语句124返回返回 (3)for语句功能最强,可完全取代while和do-while语句;(4)while和do-while语句中循环变量初始化应该在循环前提前完成,并在while后指定循环条件,循环体中要包含使循环趋于结束的语句,而for循环可把这些操作放在for语句当中。(relativeexamples:p53_5.cpp:关于if语句,统计.cpp:关于

95、while和if语句p53_6.cpp:关于switch语句,水仙花数.cpp:关于for语句九九乘法表.cpp,组合.cpp:关于for和if打印图形.cpp:关于foraboutgoto.cppaboutbreak.cpp数列和.cpp,控制结构例.cpp译成密码.cpp完数.cpp,p76_10.cpp一个数列的前n项的输出.cpp输出集合的各个子集.cpp打印数字魔方.cpp显示数字的和.cpp)2.5 C+的控制语句的控制语句125返回返回 2.6 数组及其使用数组及其使用前面已经讲过基本数据类型,如:整型,字符型,实型等,C+语言还提供了构构造造数数据据类类型型,如:数组、结构体、

96、联合体等,有的书中也叫”导出数据类型”,本节先介绍数组。数组数组是由若干相同数据类型的数据所组成的有序集合。数组中每一个数据又称为数组元素数组元素,它们之间具有固定的先后顺序。用一个统一的数组名和下标下标来唯一地确定数组中的元素。凡是具有一个下标的数组称为一维数组,具有两个或两个以上下标的数组称为多维数组。 2.6 数组及其使用数组及其使用126返回返回 2.6 数组及其使用数组及其使用2.6.1 一维数组一维数组2.6.1.1 一维数组的定义一维数组的定义一维数组定义的一般格式为:类型说明标识符数组名常量表达式;如:intb5;对定义作几点说明:(1)数组名的命名遵循C+语言标识符的命名规则

97、;(2)数组名后边是用括起来的常量表达式,而不能用圆括号。127返回返回 (3)常量表达式表明该数组的长度,即数组中元素的个数。如:intb5;表示b数组中共有5个元素。 (4)常量表达式中可可以以包包括括常常量量和和符符号号常常量量,不不能能为为变变量量,即不允许对数组的大小作动态定义。如以下定义不正确:intn;scanf(“%d”,&n);intan;2.6.1.2 一维数组的引用一维数组的引用一维数组中各元素在内存中所占的存储单元按下标序号顺顺序序存存放放,C+语言规定,只能逐个引用数组中的元素,而不能一次引用整个数组不能一次引用整个数组,而数组元素的表示形式为:数组名下标2.6 数组

98、及其使用数组及其使用128返回返回 【例例2-14】定义一个一维数组,把各元素值清0,并输出各元素值。#includevoidmain()inti;intb5;for(i=0;i=0;i-)coutbiendl;2.6 数组及其使用数组及其使用129返回返回 2.6 数组及其使用数组及其使用2.6.1.3 一维数组的初始化一维数组的初始化可以用赋值语句或输入语句使数组中的元素得到值,也可以使使数数组组在在运运行行之之前前初初始始化化,即即在在编编译译阶阶段段使使之之得得到到初初值值,可用以下几种方法:(1)在定义数组时对数组元素赋以初值,如:inta5=0,1,2,3,4;将数组元素的初值放在

99、一对大括号内,各值之间用逗号隔开。定义后的结果为:a0=0,a1=1,a2=2,a3=3,a4=4(2)可以只给一部分元素赋值,如:inta5=0,1,2;这 说 明 a数 组 中 5个 元 素 只 有 3个 元 素 赋 初 值 。 即:a0=0,a1=1,a2=2,后两个元素的值为0。(p125:全局或静态数组为0,局部数组为不确定值)130返回返回 (3)如果想使一个数组中全部元素值为0,可以写成inta5=0,0,0,0,0;/或inta5=0;但不能inta5=;(4)在对全部全部元素赋初值时,可以不指定数组的长度。如:intb5=0,1,2,3,4;可写成:intb=0,1,2,3,

100、4;2.6.2 二维数组二维数组2.6.2.1 二维数组的定义二维数组的定义二维数组定义的一般形式为:类型说明符号数组名常量表达式常量表达式如:inta34;这就定义了一个3*4(3行4列)的数组。2.6 数组及其使用数组及其使用131返回返回 注意:不能写成inta3,4;的形式。如:inta34;可以把它看作是一个一维数组看作是一个一维数组,它有3个元素a0,a1,a2,这每个元素又是一个分别含4个元素的一维数组:a0a00,a01,a02,a03aa1a10,a11,a12,a13a2a20,a21,a22,a23C+语言中,二维数组中元素在计算机内存中的存放顺序是:按行存放按行存放,即

101、先在内存中存放第一行的元素,再放第二行的元素,如:a00,a01,a02,a03,a10,a11,a12,a13等2.6 数组及其使用数组及其使用132返回返回 2.6.2.2 二维数组的使用二维数组的使用二维数组元素的表示方式为:数组名下标下标注意下标不要超过各维的大小。2.6.2.3 二维数组的初始化二维数组的初始化对于二维数组有下列初始化方法:(1)分行给二维数组赋初值,如:inta34=1,2,3,4,5,6,7,8,9,10,11,12;这种赋值方法比较直观,把第一对括号内的数值赋给第一行的元素,第二括号内的数值赋给第二行的元素,依此类推。2.6 数组及其使用数组及其使用133返回返

102、回 (2)可以将所有数据写在一个花括号内,这时,计算机自动按数组元素在内存中的排列顺序对各元素赋初值。如inta34=1,2,3,4,5,6,7,8,9,10,11,12;(3)可以只对数组中部分元素初始化。如:inta34=1,5,9;此处的作用表示:a00元素被赋成1,a10元素被赋成5,a20元素被赋成9,而数组中的其他元素被初始化为0。(p131:全局或静态数组为0,局部数组为不确定值)(4)如果对二维数组的全部元素初始化,则定义数组时第一维长度可以省略,但第二维长度不能省第二维长度不能省,如:inta34=1,2,3,4,5,6,7,8,9,10,11,12;可写成:inta4=1,

103、2,3,4,5,6,7,8,9,10,11,12;也可以只对部分元素初始化而省略第一维的长度,但应2.6 数组及其使用数组及其使用134返回返回 分行进行初始化,如:inta4=0,0,3,0,10;/?应为inta4=0,0,3,0,0,10;p1322.6.3 字符数组字符数组1.字符数组的定义用来存放字符型数据的数组为字符数组,数组中的一个元素中只能存放一个字符,整个数组可以存放一个字符串。如:charc5;2字符数组的初始化字符数组的初始化方式同一维数组的初始化类似,如:charc5=a,b,c,d,e;/chars3=a,b,0;3字符和字符串结束标志:2.6 数组及其使用数组及其使

104、用135返回返回 在C+语言中字符串是以0代表结束标志。如:“C.program”是9个字符的字符串,但在内存中占10个字节,最后一个字节存放0。注意:字符串只能用字符数组或字符指针来来保存,不不能能用用一一个个简简单单的的字字符符变变量量保保存存,另外,字符数组的初始化方式也可写为:charc10=“C.program”;/orchars=“abcdef”;4字符串的输出:对于字符串的输出可以采用下列方法来完成:(1)用cout格式是:cout字符串或字符数组名;如:设有:chars20=Thisisastring.;则couts;的输出结果为Thisisastring.。也可直接输出字符串

105、,如:coutThisisastring.2.6 数组及其使用数组及其使用136返回返回 (2)用cout流对象的put方法,格式是:cout.put(字符或字符变量);利用这种方法,每每次次只只能能输输出出一一个个字字符符,所以要输出整个字符串,应采用循环的方法。如:#includevoidmain(void)chars20=Thisisastring.;inti=0;while(si!=0)cout.put(si);i+;2.6 数组及其使用数组及其使用137返回返回 (3)用cout流对象的write方法,格式是:cout.write(字符串或字符数组名,个数n);其作用是输出字符串中的

106、前输出字符串中的前n个字符个字符。如:#includevoidmain()chars20=Thisisastring.;cout.write(s,4);该程序的输出结果为This5字符串的输入:除了可以在程序中利用字符数组初始化的方法或赋值方法将字符串存放到字符数组外,还可以采用以下方法,但要注意,只能用字符数组(orpointer)接收输入的字符串。2.6 数组及其使用数组及其使用138返回返回 (1)利用cin直接输入。格式是:cin字符数组名;如:#includevoidmain()chars20;cins;couts;当程序运行时,输入abcde并回车时,则输出结果为abcde,但当输

107、入当输入ab cde时,输出结果为时,输出结果为ab。因此,这种方法输入字符串时,cin只能接收空格符之前的部分只能接收空格符之前的部分。无法完成接收全部的字符串。2.6 数组及其使用数组及其使用139返回返回 (2)利用cin流对象的getline方法。格式是:cin.getline(字符数组名或字符型指针,输入字符串的最大长度n);/cin.getline(char*s,intm,charch=n);其中:参数“字符数组名”是存放字符串的数组名称;参数“输入字符串的最最大大长长度度n”包包括括字字符符串串结结束束标标记记0在在内内。即最多只能读n-1个字符。(第三个参数ch设置读取字符串时

108、的结束标志符,默认值是“n”)如:#includevoidmain()chars20;cin.getline(s,20);couts;2.6 数组及其使用数组及其使用140返回返回 当程序运行过程中输入abcdef并回车时,程序的输出结果为abcdef。而当输入abcdef回车时,程序的输出结果为abcdef。由此可见,该该种种方方法法可可以以接接收收含含有有空空格格符符的的字符串字符串。(3)利用cin流对象的get方法。格式是:格式1:cin.get(字符数组名或字符指针,输入字符串的最大长度n);格式2:字符变量名=cin.get();/orcin.get(字符变量名);说明:格式1中的

109、两参数的含义同getline方法。格式2表示输入一个字符,如果要保存该字符,则在其左边写上被赋值的变量名和赋值号,也可写为cin.get(字符变量名);2.6 数组及其使用数组及其使用141返回返回 #includevoidmain(void)chars20;charc;cin.get(s,10);couts;c=cin.get();coutc;当程序运行过程中输入abcdef并回车时,程序的输出结果为abcdef(couts)和换行(coutc)。由此可见,字符串abcdef被接收到字符数组s中,而输入过程中的换行符n被接收到了变量c中。这说明输入(cin.get(s,10)过程中的换行符换

110、行符n并未接收,而还残留在并未接收,而还残留在输入输入缓缓冲区中冲区中。这一点也是cin.get与cin.getline间的区别。(如改用getline,则执行cin.get()时将等待输入)2.6 数组及其使用数组及其使用142返回返回 关于函数intgetch(void)、intgetche(void)和intgetch(void)的说明:函数getch()返回读自控制台的下一个字符,但读入的字符在屏上不可见。函数getche()返回读自控制台的下一个字符,但读入字符回显到屏上。两个函数都未在ANSI标准中定义,但基于DOS的C编译程序常提供之(#include”conio.h”)。他们都

111、饶过C的标准I/O功能,直接与操作系统作用。本质上它们都直接实施读键盘操作。函数getchar(void)(#include”stdio.h”)从stdin返回下一字符。字符先按unsignedchar型读入,转为int型后返回。2.6 数组及其使用数组及其使用143返回返回 Examples:( ch7_2.cpp 冒泡排序的变形.cpp ch7_3.cpp 选择排序的变形.cpp (选择排序的变形2.cpp) ch7_5的变形.cpp 插入排序的变形.cpp ch7_6.cpp 扬辉三角的数组实现.cpp ch7_7的变形.cpp Josephus问题.cpp ch7_8的变形2.cpp

112、Josephus问题另解.cpp 快速排序.cpp (ch7_11.cpp?) 随机数字序列的产生.cpp二维数组元素的赋值.cpp 把表转换为一维的数组.cpp 填充矩阵.cpp 二维数组行和列的平均值.cpp)2.6 数组及其使用数组及其使用144返回返回 一个C+程序是由若干个源程序文件构成的,而一个源程序文件是由若干个函数构成。从用户的角度看,有两种不同的函数:库函数和用户自定义函数。所谓库函数也称标准函数,由C+系统提供。而用户自定义函数则需要用户先定义,后使用。2.7.1 函数的定义函数的定义2.7.1.1 函数的定义格式函数的定义格式定义函数的一般形式:函数返回值的数据类型标识符

113、函数名(形式参数表及其类型)函数体2.7 函数函数145返回返回 2.7 函数函数如:voiddisplay_larger(intx,inty)if(xy)coutThelargeris:yy)coutThelargeris:xn;elsecoutTwovaluesareequal.xy;c=max(a,b);cout“maxis”y?x:y;return(z);2.7 函数函数149返回返回 关于形参和实参说明几点:(1)实参可以是变量、常量、或表达式,但必须有确定的值。而形参必须是变量。(2)形参变量,只有存在发生函数调用时,形参才被分配存储单元,在调用结束时,形参所占的内存单元被释放。(

114、3)实参与形参的类型必须一致,否则会发生“类型不匹配”的错误。(4)实参对形参的数据传递是“值值传传递递”,即即单单向向传传递递。由实参把数据传给形参,并且存储单元与形参是不同的单元,并将实参对应的值依次传递给形参变量。调用结束后,形参单元被释放,而实参单元保留并维持原值。(例:p163例ch8_12.cpp,值参数传递方式.cpp参数传递方式.cpp)2.7 函数函数150返回返回 2. 函数的返回值:函数的返回值:(1)函数的返回值是通过函数中的return语句获得的,return语句的格式为:return(表达式);或return表达式;return语句的功能有两个,(A)强制程序执行的

115、流程从被调函数返回到主调函数(B)给主调函数带回一个确定的函数值如:intmax(inta,intb)return(ab?a:b);2.7 函数函数151返回返回 (2)函数值的类型:函数返回值的类型就是在定义函数时的函数值的类型。在在定定义义函函数数时时,函函数数值值说说明明的的类类型型和和return语语句句中中的的表表达达式式类类型型不不一一致致时时,则则以以函函数数类类型为准。型为准。(3)如果被调用函数中没有return语句,为了明确表示函数“不返回值”,要用void定义无类型定义无类型。如:voidprint()printf(“clanguage”);这样系统就保证不使函数带回任何

116、值。/函数的定义和使用例.C螺旋队列.cpp2.7 函数函数152返回返回 2.7.2 函数的调用函数的调用 1函数调用的格式函数调用的格式函数名(实参数)如果调用的是无参函数,则实参表可略去,但函数的括号不能省.如果实参表中有多个参数,之间用逗号隔开,实参的类型、个数应与形参顺序一一对应。函数通过下列三种方式完成函数调用:(1)函数调用语句:即以一个函数的调用后面加上“;”作为一个语句。如:printf();(2)函数表达式:即函数出现在一个表达式中,这时要求函数带回一个确定的值以参加表达式的运算。如:c=2*max(a,b);2.7 函数函数153返回返回 (3)函数参数:以函数的调用作为

117、一个函数的实参。如:M=max(a,max(b,c);2调用函数时的前提条件调用函数时的前提条件在一个函数中调用另一个函数,需要具备的条件:(1)首先被调用的函数必须已经存在的函数。如果调用库函数,一般还应在本文件的开头用#include命令将调用有关库函数时所需用到的信息包含到本文件来。(2)如果调用用户自己定义的函数,则必必须须对对被被调调函函数数的的原原型型进进行行说说明明(否否则则必必须须函函数数先先定定义义,后后才才能能被被调调用用),函数的原型包括:函数值的类型标识符被调用函数名(形参及其类型表);(3)对函数原型的说明,通常放在程序的顶部,也可以存放到一个头文件中,然后利用#in

118、clude语句嵌入到程序中。/Demo:mymain.cpp+myheaderfile.H2.7 函数函数154返回返回 3函数的定义与函数函数的定义与函数原型说明之原型说明之间的区别间的区别(1)函数的“定义”是一个函数功能的确立,包括指定函数名,函数返回值的类型,形参及其类型,函数体等,它是一个完整的、独立的函数单位。(2)函数的原型说明则只是对将要使用的函数进行“框架”说明,它包括函数类型、函数名、一对括号及其括号内的各个函数形参的类型。形参名可以省略。(3)对函数进行原型说明的作用是告诉系统,在本程序中将要用到的函数是什么样的“结构模型”,以便确保在主调函数中必须按此“模型”对函数进行

119、调用(即要匹配)。2.7 函数函数155返回返回 2.7.3 函数的嵌套调用函数的嵌套调用C+语言中函数的定义是平行的、独立的,所以,函函数数的的定定义义是是不不能能嵌嵌套套进进行行的的,但但函函数数的的调调用用可可以以。嵌套调用即在调用一个函数的过程中,又调用另一函数。2.7 函数函数main()函数 调用a函数 a( )函数 调用b函数 b( )函数 156返回返回 在本例中,main函数在执行过程中,调用了函数a,而函数a中又调用了函数b,所以,这就是一种嵌套调用。要注意:在函数嵌套调调用过程中程序执行的流程和返回点的问题。2.7 函数函数157返回返回 2.7 函数函数2.7.4 函数

120、的递归调用函数的递归调用1函数递归调用的概念函数的递归调用就是当一个函数在执行的过程中,出现了直接或间接地调用函数本身的函数调用方式。下面定义求n!的函数。longfact(longn)if(n=1)return1;returnfact(n-1)*n;/出现了函数fact自己直接调用本/身的函数调用要正确地理解函数的递归调用时,程序执行的流程和返回点。158返回返回 2.7 函数函数递归是用自己定义自己的过程,有时称为循环定义(circular definition)。递 归 的 例 子 很 多 。 例 如 , 整 数 的 一 个 递 归 定 义 是 :0,1,2,3,4,5,6,7,8,9加

121、或减一个整数是整数。因此,15是8加7,21是9加12,12是9加2,等等。函数调用自己时,在栈上为局部变量和参量分配存储空间,从头执行函数代码。递归调用并不复制函数代码,只是新分配相应变量。每个递归调用返回时,其局部量和参数的存储空间都释放回栈中,执行在函数中的调用点继续。许多函数的递归版本比等价的叠代版本运行得慢,原因在于反复调用得开销太大。实际上,过分递归可以溢出堆栈。递归函数的主要优点是能够生成某些算法的更清晰、更简洁的版本。如快速排序算法就很难用叠代方法实现。此外,某些问题(特别是人工智能有关的问题)本质上是递归的,特别适合递归解。最后,有些人认为递归比叠代更便于思考。159返回返回

122、 2.7 函数函数 2 2函数递归调用的条件函数递归调用的条件 递归调用的条件也是我们在定义一个递归函数时应该遵循的原则。(1)必须有完成函数任务的语句。如:上例求n!中的return 1;(2)有一个确定是否能避免递归调用的测试条件。如果条件不满足时就递归调用,否则就不再递归调用。(3)有一个递归调用语句,并且该递归调用语句的参数应该逐渐逼近不满足条件,以致最后断绝递归。(4)先测试,后递归调用。在递归函数定义中,必须先测试,后递归调用。也就是说,递归是有条件的,满足了条件后,才可以递归。(例:递归函数例3.cpp,递归函数例4.cpp,递归函数例1.cpp,递归函数例2.cpp,递归函数例

123、6.C,递归函数例-整数的逆向输出.cpp,递归函数实例.cpp,牛数的递归算法2.cpp,牛数的递归算法1.cpp,汉诺塔问题.cpp,递归函数例5.cpp,递归函数例子.cpp走台阶问题.cpp,最大公约数的递归解法.cpp,递归求满足不等式的n值.cpp十进制转化为二进制递归解法.cpp)160返回返回 2.7 函数函数2.7.5 局部变量和全局变量局部变量和全局变量从程序中各个变量起作用的范围(作用域)来看,变量可以分为局部变量和全局变量。1. 局部变量局部变量在一个函数的内部定义的变量就是内部变量(局部变量)。如:floatf1(inta)intb,c;/a,b,c有效voidmai

124、n(void)intn,m;/m,n有效161返回返回 2.7 函数函数对局部变量作以下几点说明:(1)局部变量的作用范围(作用域):只局限在定义它的本函数体之内。(2)局部变量的生存期(存在的时间):只有当程序执行到本函数时,才给这些局部变量分配存储单元,当本函数执行完毕后,这些局部变量所占存储单元就被释放。(3)不同函数体中可以定义相同名字的变量,但它们代表不同的对象,互不干扰。它们在内存占用不同的内存单元。(4)函数的形式参数也是该函数的局部变量,其他函数不能调用。(5)在一个函数内部,可以在复合语句中定义变量,但这些变量只在本复合语句中有效,因此,复合语句也可称为“分程序”或“程序块”

125、。162返回返回 2.7 函数函数(6)局部变量又可称自动变量(auto),(因为可以用关键字auto说明之)。使用auto存储类型定义的变量称为自动变量,编译系统在堆栈区(内存的一部分)为它分配内存空间。分配和释放空间的操作都由系统自动完成,故称为自动变量。函数内定义的自动变量关键字auto可以缺省。163返回返回 2.7 函数函数2静态局部变量(局部静态变量):静态局部变量(局部静态变量):定义方法是:在函数体内定义变量采用:static类型标识符变量名;特点:(1)静态局部变量本身也是局部变量,因此其作作用用域域也是局限在定义它的本函数体内,当离开本函数体,该变量就不再起作用,但其值还继

126、续保留。(2)另一方面,静态局部变量又是静态存储类别的变量,所以,在整个程序运行开始就被分配固定的存储单元(占用静态存储区),整个程序运行期间不再被重新分配,所以其生存期生存期是整个程序运行期间。(3)静态局部变量的赋初值的时间在编译阶段,并不是每发生一次函数调用就赋一次初值。当再次调用该函数时,静静态态局局部部变变量量保保留留上上次调用函数时的值次调用函数时的值。(例:static.cpp)164返回返回 2.7 函数函数3全局变量:全局变量:在所有函数体外部定义的变量为外部变量(全局变量),全局变量可以被本文件中其他函数所调用(使用)。全局变量的有效范围为:从定义该变量的位置开始到本程序文

127、件的结束。如:intp=1,q=5;/*全局变量*/floatf1(inta)intb,ccharc1,c2;/* 全局变量 */165返回返回 2.7 函数函数charf2(intx,inty)inti,j;main(void)intm,n.;对全局变量的几点说明:(1)全局变量在程序的全部执行过程中都占用固定的内存储单元,而不是仅在需要时才开辟单元,所以其生生存存期期是整个程序运行期间。166返回返回 2.7 函数函数(2)全局变量的作用范围是整个程序文件。全局变量处于文件的开头定义时,其作用范围为整个文件,否则在在定定义义点点之之前前的的函函数数内内使使用用时时,应应在在函函数数体体内内

128、或或外外部部用用extern说说明明。说明的格式是:extern类型标识符变量名;/aboutglobal1.cppandaboutglobal2.cpp(3)在一个程序文件中定义的全局变量,要在同一程序的另外一个程序文件中使用时,应在使用它的程序文件中所有函数体内部或外部对所使用的全局变量用extern说明(外部变量)。(例:externvariation.cpp+myfun.h+myfun1.cpp+myfun2.cpp)(4)在同一个文件中全局变量与局部变量同名时,则在局部变量的作用范围内,全局变量不起作用。(可以使用域作用符:访问全局变量)(例域作用符.cpp)4静态全局变量静态全局变

129、量当在所有函数体的外部用如下格式定义变量时,则这种变量称为静态全局变量。static类型标识符变量名;167返回返回 2.7 函数函数静态全局变量的特点是:(1)与全局变量基本相同,只是其作作用用范范围围(即作用域)是定义它的程序文件,而不是整个程序。(2)静态全局变量属于静态存储类别的变量,所以它在程序一开始运行时,就被分配固定的存储单元,所以其生生存存期期是整个程序运行期间。(3)使用静态全局变量的好好处处是同一程序的两个不同的程序文件中可以使用相同名称的变量名,而互不干扰。注:变量的类型还有寄存器类型(register)例aboutregister.cpp小小结结:从变量作用域和生存期的

130、角度出发,把覆盖了从定义点开始到整个程序结束的变量称为具有全局作用域和全局寿命的变量,简称为“全局变量”(Global Variable),而把作用域和生存期只覆盖了某个函数或某个复合语句的变量称为具有局部作用域和局部寿命的变量,简称为“局部变量”(Local Variable),它包含如下存储168返回返回 2.7 函数函数类型的变量:自动变量、静态局部变量、寄存器变量和形参(形参也是自动型,也可说明为寄存器变量)。(注注意意局局部部静静态态变变量量的的生生存存期期是是整整个个程程序序)在所有函数外定义的变量称为外部变量,若将它的作用域限制在一个源文件内,需加上关键字static,称为静态全

131、局变量。这两种变量统称为全局变量。2.7.6 全局函数和静态函数全局函数和静态函数1全局函数全局函数(类似全局变量类似全局变量)凡程序中定义的函数,如果未做特别说明,一律都是全局的。也就是说,函数从本质上是全局的,一个程序不管有多少个程序文件所组成,在在某某个个程程序序文文件件中中可可以以调用同一程序的另外一个程序文件中定义的函数调用同一程序的另外一个程序文件中定义的函数169返回返回 2.7 函数函数(可可以以缺缺省省extern关关键键字字),只只要要对对被被调调函函数数的的原原型型进进行行说说明明即即可可。声明函数原型的语句:类型标识符函数名(形参类型表);如:假设程序中定义了max函数

132、,则:intmax(int,int);就是对函数max原型的声明。(例函数原型.cpp)(例externvariation.cpp+myfun.h+myfun1.cpp+myfun2.cpp)2静态函数静态函数因为函数多数为外部型的,必然产生不同源文件中同名函数的冲突。若将某一重要函数定义为静态型(static),则只能被该函数所在文件的其它函数调用,而不能被其它源文件的函数调用。静态函数定义方法为:static类型标识符函数名(形参及其类型)函数体注意:这种函数就只能在定义它的程序文件中调用只能在定义它的程序文件中调用。170返回返回 2.7 函数函数2.7.7 内联函数内联函数1内联函数的

133、定义方法和格式:内联函数的定义方法和格式:inline函数值的类型函数名(形参及其类型列表)函数体如:inlinedoublesquare(doublex)returnx*x;voidmain(void)doublex;coutx;cout”thesqureis“square(x);171返回返回 2.7 函数函数2内联函数与普通函数的区别和联系内联函数与普通函数的区别和联系( 1) 在 定 义 内 联 函 数 时 , 函 数 值 的 类 型 左 面 有“inline”关键字,而普通函数在定义时没有此关键字。(2)程序中调用内联函数与调用普通函数的方法相同。(3)当在程序中调用一个内联函数时,

134、是将该函数的代码直接插入到调用点,然后执行该段代码,所以在在调调用用过过程程中中不不存存在在程程序序流流程程的的跳跳转转和和返返回回问问题题。而普通函数的调用,程序是从主调函数的调用点转去执行被调函数,待被调函数执行完毕后,再返回到主调函数的调用点的下一语句继续执行。(4)从调用机理看,内联函数可加快程序代码的执行速度和效率,但这是以增加程序代码为代价来求得速度的。172返回返回 2.7 函数函数3对内联函数的限制对内联函数的限制应注意:不是任何一个函数都可定义成内联函数。(1)内联函数的函数体内不能含有复杂的结构控制语句,如:switch和while,如果内联函数的函数体内有这些语句,则编译

135、将该函数视同普通函数那样产生函数调用代码。(2)递归函数不能被用来作为内联函数。(3)内联函数一般适合于只有15行语句的小函数,对一个含有很多语句的大函数,没有必要使用内联函数来实现。173返回返回 2.7 函数函数2.7.8 函数重载函数重载1. 什么是函数重载什么是函数重载函数重载是指一个函数可以和同一作用域中的其他函数具有相同的名字,但这些同名函数的参数类型、参数个数、返回值、函数功能可以完全不同。如:#includevoidwhatitis(inti)coutthisisintegeriendl;voidwhatitis(charc)cout“thisisstring”cendl;vo

136、idmain()inti=1;charc=abcdef;174返回返回 2.7 函数函数whatitis(i);whatitis(c);/函数重载示例1.cpp在本例中定义了两个名称都叫whatitis的函数,但它们的形参类型不同。因此,这两个函数就是重载函数。2为什么要使用函数重载为什么要使用函数重载在原有C语言中,每个函数必须有其唯一的名称,这样的缺点是所有具有相同功能、而只是函数参数不一样的函数,就必须用一个不同的名称,而C+中采用了函数重载后,对于具有同一功能的函数,如果只是由于函数参数类型不一样,则可以定义相同名称的函数。3匹配重载函数的顺序匹配重载函数的顺序由于重载函数具有相同的函

137、数名,在进行函数调用时,175返回返回 2.7 函数函数系统一般按照调用函数时的参数个数、类型和顺序来确定被调用的函数。具体来说,按以下三个步骤的先后次序找到并调用那个函数:(1)寻找一个严格的匹配,即:调用与实参的数据类型、个数完全相同的那个函数。(2)通过内部转换寻求一个匹配,即:通过(1)的方法没有找到相匹配的函数时,则由由C+系系统统对对实实参参的的数数据据类类型型进进行行内内部部转转换换,转换完毕后,如果有匹配的函数存在,则执行该函数。(3)通过用户定义的转换寻求一个匹配,若能查出有唯一的一组转换,就调用那个函数。即:在函数调用处由由程程序序员员对对实实参参进进行行强强制制类类型型转

138、转换换,以此作为查找相匹配的函数的依据。如:176返回返回 2.7 函数函数#includevoidprint(doubled)coutthisisadoubledn;voidprint(inti)coutthisisanintegerin;voidmain(void)intx=1,z=10;floaty=1.0;charc=a;print(x);/按规则(1)自动匹配函数voidprint(inti)print(y);/按规则(2)通过内部转换匹配函数/voidprint(doublei)177返回返回 2.7 函数函数/因为系统能自动将float型转换成double型print(c);/按

139、规则(2)通过内部转换匹配函数/voidprint(inti)/因为系统能自动将char型转换成int型print(double(z);/按规则(3)匹配voidprint(doublei)/因为程序中将实参z强制转换为double型。/函数重载示例2.cpp4. 定义重载函数时的定义重载函数时的注意事项注意事项(1)重重载载函函数数间间不不能能只只是是函函数数的的返返回回值值不不同同,应应至至少少在在形参的个数、参数类型或参数顺序上有所不同形参的个数、参数类型或参数顺序上有所不同。如:178返回返回 2.7 函数函数voidmyfun(inti)intmyfun(inti)这种重载就是错误的

140、。(2)应使所有的重载函数的功能相同。如果让重载函数完成不同的功能,会破坏程序的可读性。179返回返回 2.7 函数函数2.7.9 默认参数的函数默认参数的函数1. 默认参数的函数默认参数的函数C+允许在定义函数时给其中的某个或某些形式参数指定默认值,这样,当发生函数调用时,如果省略了对应位置上的实参的值时,则在执行被调函数时,以该形参的默认值进行运算。如:#includevoidsum(intnum=10)/形参默认值inti,s=0;for(i=1;i=num;i+)s=s+i;coutsumissn;voidmain(void)sum(100);/提供了实参值,被调函数以100进行运算,

141、/输出结果为5050sum();/省略实参值,使用形参默认值10,输出结/果为55180返回返回 2.7 函数函数2. 使用默认参数的函数的使用默认参数的函数的注意事项注意事项(1)默认参数一般在函数说明中提供。如如果果程程序序中中既既有有函函数数的的说说明明又又有有函函数数的的定定义义时时,则则定定义义函函数数时时不不允允许许再再定定义义参参数数的的默默认认值值。如如果果程程序序中中只只有有函函数数的的定定义义,而而没没有有说说明函数,则默认参数才可出现在函数定义中明函数,则默认参数才可出现在函数定义中。如:voidpoint(intx=10,y=20);voidmain(void)void

142、point(intx,inty)coutxendl;coutyendl;181返回返回 2.7 函数函数(2)默认参数的顺序:如果一个函数中有多个默认参数时,则形参分布中,默认参数应从右至左连续定义,即指定和不指定不能交叉。如:voidmyfunc(inta=1,floatb,longc=20);/错误voidmyfunc(inta,floatb=2.1,longc=30);/正确(3)当进行调用时,实参数目少于形参时,编译系统按从右到左的顺序用默认值来补足所缺少的实参。(从左到右使用实参,右边剩余的使用默认参数)(例函数的默认参数.cpp)182返回返回 补充:命名空间补充:命名空间本节讨论

143、在C+标准中介绍的命名空间的基本概念。命名空间提供了一种在程序内和程序之间组织和使用名称的技术。1.背景给人和物命名可能是困难的。在家庭内部可以说出不同的家庭成员的名称,比如John、George、Ann和Alice。在家庭内,当说到Ann的时候,每个人都知道谈论的是谁。然而在家庭之外,有许多名叫Ann的人。当需要在家庭外部谈论她的时候,可能需要限定她的名称,需要说明谈论的是哪一个Ann,否则有人可能想到另一个名为Ann的人。183返回返回 补充:命名空间补充:命名空间为了限制谈论的是哪一个Ann,一种方法是将她与家庭名称相联系。例如,在Washingtons家庭内部,每个人都用Ann的名字称

144、呼她;在Nguyens家庭内部,每个人也都用Ann的名字称呼这个家庭的Ann。但是在家庭外部 , 她 们 被 称 为 ”Washingtons,Ann”和”Nguyens,Ann”。分开姓和名的逗号称为家庭分辨操作符。在编程的过程中,特别对于大型程序而言,也有相同的问题。我们需要命名程序内的常数、变量、函数和其他对象。但是当我们自己、其他项目组成成员或者系统程序员将我们的程序与其他程序结合在一起时,将出现什么情况?有些名称可能用在不止一个函数或者对象中。现在遇到了麻烦,如果两个程序段使用相同的名称比如num来定义一个整数,那么当引用num时,究竟指的是哪一个num是不清楚的。184返回返回 补

145、充:命名空间补充:命名空间为了解决这个问题,C+定义了命名空间。命名空间是属于相同组的名称的集合。例如,可以有两个组:G1和G2。如果在每个组内定义一个名为num的变量,那么就可以没有任何歧义地在G1内部或者在G2内部引用num。但是如果需要在组外引用num,则必须用作用域分辨符(:)来限定名称。换句话说,G1内的num叫G1:num,而G2内的num叫G2:num。下图显示出C+如何使用命名空间来定义命名空间。namespaceG1namespaceG2intnum;intnum;/namespaceG1/namespaceG2G1:num=5;G2:num=10;185返回返回 补充:命名

146、空间补充:命名空间为了使这个概念清晰,现在编写一个非常不寻常的程序。虽然永远不建议这样做,但是这里还是编写了一个两次使用名称cout的程序。第一个cout是一个变量名(值为5)的名称,因为它没有使用作用域分辨操作符,所以它的作用域局限于程序中的main。第二个cout使用了作用域分辨操作符,它将cout名称与std命名空间相联系,该命名空间定义所有在c+程序库中使用的名称。当使用cout时,编译器知道它应该检查程序内的声明,当使用std:cout时,该程序在我们的程序内找不到这个全称(姓和名),因此它尝试在头文件内寻找,并且在头文件内发现了这个名称。以下程序包含这个程序的代码和结果。186返回

147、返回 补充:命名空间补充:命名空间/*Demonstratenamespacescope.*/#includeintmain()intcout=5;std:coutcout“n”;return0;/mainResult:5程序证明:cout和std:cout是完全不同的两个名称。一个属于全局命名空间,另一个属于std命名空间。187返回返回 补充:命名空间补充:命名空间为了进一步研究,现在编写一个仅使用cout作为输出流名称的程序。/Demonstratenotinscopeerror.#includeintmain()cout“Hellon”;return0;/mainResults:Err

148、or:undefinedidentifiercout0这个程序不能编译,因为编译器要寻找cout的声明,但是却没有发现。它既没有在程序内,也没有在iostream文件内发现cout的声明。iostream文件使用的是std:cout,而不是cout。188返回返回 补充:命名空间补充:命名空间2.使用命名空间的名称为了使用特定命名空间的名称,有3种选择:写出全称、添加使用命令或者添加使用声明。(1)全称可能解决这个问题最简单的方法就是使用全称。尽管这样更简单,但是它需要更多的击键,而且程序更长。当使用全称时要将该命名空间的家族名称(比如std)和作用域分辨操作符添加到名称上。因此,cout变成

149、std:cout。如:#includevoidmain()std:coutnumIn;std:cout“Youentered:“numIn“n”;189返回返回 补充:命名空间补充:命名空间(2)使用命令第2种解决方法是添加名为使用命令的语句,通常将其放在包含语句后面的程序全局区域。语句格式如下所示。它必须以分号结束。usingnamespacename_of_namespace;当编译器遇到未声明的名称时,它就将using命令定义的命名空间的名称添加到未声明的名称上,然后试图发现这个全称的生命。我们这次使用命名空间命令来命令编译器,为所有找不到的名称使用std命名空间。190返回返回 补充:

150、命名空间补充:命名空间#includeusingnamespacestd;voidmain()coutnumIn;cout“Youentered:“numIn“n”;/main191返回返回 补充:命名空间补充:命名空间(3)使用声明使用命令的方法将命名空间的名称添加到每一个编译器找不到的名称。第三种解决方法使用声明,对编译器试图解析的名称进行了限制。它告诉编译器只将命名空间添加到选定数量的名称上,而不是全部找不到的名称上。其格式如下:usingname_of_the_namespace:identifier;当编译器遇到的名称包含在using声明内声明的标识符时,它就添加命名空间的名称,并再

151、次尝试。例如,下面程序增加了两条使用命名空间的声明,来命令编译器只将std添加到cin、cout和endl;192返回返回 补充:命名空间补充:命名空间#includeusingstd:cout;usingstd:cin;usingstd:endl;voidmain()coutnumIn;cout“Youentered:“numIn“n”;/main193返回返回 补充:命名空间补充:命名空间(4)命令和声明之间的区别使用声明将它的名称添加到局部作用域,使用命令使名称在声明她们的作用域内(通常是编译单元)可以使用。命名空间的命令和声明之间的另一个主要区别是,using语句包括的名称数量不同。命

152、令添加所有命名空间内的名称,而声明只添加指定的名称。通常使用声明更安全,尤其是在多于一个名称空间时。看 一 个 例 子 , 假 设 有 两 个 命 名 空 间 : purchasing和inventory。她们在程序内声明,都有两个普通的名称:i和j。这里想使用来自purchasing的i和来自inventory的j。如果在这种情况下使用命令,编译器将产生错误。但是,声明就可以限制能够使用的变量,并且不会出现错误。命令编译器每当发现i时就使用purchasing:i,而每当发现j时就使用inventory:j。194返回返回 补充:命名空间补充:命名空间#includeusingnamespa

153、cestd;namespacepurchasinginti;intj;/purchasingnamespacenamespaceinventoryinti;intj;/inventorynamespaceusingpurchasing:i;usinginventory:j;/usingnamespaceinventory;voidmain()i=5;cout“Purchasingiis:”purchasing:iendl;j=12;cout“Inventoryjis:”inventory:jendl;coutijstd:endl;/main195返回返回 补充:命名空间补充:命名空间4.声明命

154、名空间声明命名空间前面已经非正式地说明了如何声明命名空间,在本节要正式地介绍这个主题,并讨论一些与其相关的问题。(1)声明下面示例所示为命名空间的格式。它以关键字namespace开始,后面跟着一个标识符nameSp,要包含在命名空间内的声明被编码在一个块内。注意在声明结束时不需要分号。namespacenameSp/nameSp块内的声明可以是任何在程序内有效的名称,比如变量名、函数名和类名。使用数据类型声明数据名称,使用函数原型声明函数名称。196返回返回 补充:命名空间补充:命名空间(2)扩展在声明过某个命名空间之后,仍然可以扩展它的声明。例如,如果已经在头文件内声明了某个命名空间,并且

155、需要在不修改头文件的情况下添加更多的声明,那么可以用相同的名称编写新的声明。这种代码如下所示:#includeusingnamespacenameSp/nameSpExtension197返回返回 补充:命名空间补充:命名空间(3)嵌套可以在另一个命名空间的内部定义命名空间。下面例子种,声明了两个命名空间namSp和nested。与所有嵌套代码一样,建议缩进嵌套的代码以增加可读性。namespacenameSpnamespacenested/nested/outer198返回返回 补充:命名空间补充:命名空间当引用嵌套命名空间内的名称时,必须对它们加以限定。在前面的例子中,如果声明要使用命名空

156、间nameSp,那么用或者不用限定就可以引用该命名空间内的所有声明。然而,为了引用nested,必须或者使用命名空间名称和作用域操作符来限定它,或者使用命名空间的声明或者命令。以下程序显示了这些技术。199返回返回 补充:命名空间补充:命名空间#includeusingnamespacestd;namespacenumNamesinti;namespaceshrtshortshJ;/namespaceshrtnamespacelnglonglnK;/namespacelng/numNamesnamespaceusingnamespacenumNames;voidmain()i=5;cout“n

157、umNames:iis:”numNames:iendl;shrt:shJ=12;cout“numNames:shrt:shJis:“numNames:shrt:shJendl;200返回返回 补充:命名空间补充:命名空间usinglng:lnK;lnK=12345;cout“numNames:shrt:lnKis:“numNames:lng:lnKendl;在这个程序中,有几点值得分析,首先从研究命名空间的声明开始。这里首先声明了一个一级的整数类型变量,也就是说,它的作用域是numNames。然后使用了两个嵌套的命名空间声明,一个包括短整型变量,另一个包括长整型变量。在研究这些代码的时候要注意

158、,打印语句为所有的数据引用使用了全称。201返回返回 补充:命名空间补充:命名空间为了使命名空间numNames可用,包含了一个using语句。它使该命名空间内的全部声明都可见,因此在语句shrt:shJ=12中限定了它的使用。注意不必使用它的全称(numNames:shrt:shJ),这是因为语句usingnamespacenumNames;已经使命名空间shrt可见了。为了使lnK可见,usinglng:lnK;语句中使用了命名空间命令。再强调一次,只需要嵌套的命名空间名称,一级限定已经由语句usingnamespacenumName;给出了。202返回返回 补充:命名空间补充:命名空间5

159、.命名空间的类型可以有3种类型的命名空间。命名的命名的未命名的未命名的名称空间名称空间全局的全局的203返回返回 补充:命名空间补充:命名空间(1)命名的命名空间在书中,自始至终使用的都是命名的命名空间,可以声明它或者引用某个系统库。对标准系统命名空间的引用如下所示:usingnamespacestd;(2)全局命名空间当在程序内使用不属于任何命名空间的名称时,默认的命名空间就是全局命名空间。然而,在全局命名空间内并不能使它在全局区域内都可以被访问,认识到这一点很重要。作用域的标准规则仍然是强制的。提示:全局命名空间并不意味着全局作用域提示:全局命名空间并不意味着全局作用域204返回返回 补充

160、:命名空间补充:命名空间当编写程序并声明名为amt的整型变量时,它意味着amt属于全局命名空间。当编写小型程序时,使用全局命名空间更佳。当某个程序由一些包含文件组成时,特别在不同的程序员编写它们的时候,全局命名空间经常产生问题,这使因为在不同单元使用的相同名称可能具有不同的定义和不同的目的,在这种情况下,推荐设计并建立命名空间。(3)未命名的命名空间)未命名的命名空间命名空间可以没有名字。当声明的某个命名空间没有名字时,称之为未命名的命名空间。下面的示例就包括一个未命名的命名空间。namespace/unnamednamespace205返回返回 补充:命名空间补充:命名空间在一个翻译单元之内

161、,未命名的命名空间是唯一的。翻译单元是独立的可编译代码单元,它可以与其他编译单元链接以形成一个程序。最普通的翻译单元是那些随系统提供嵌入程序的代码。在大型项目内,也可能使用本地编写的翻译单元。由于未命名的命名空间在某个翻译单元之内是唯一的,因此在未命名命名空间内声明的每一个名称只能在该翻译单元内使用,它们在其他翻译单元内是不可能访问的。206返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8 指针类型及使用指针类型及使用2.8.1 指针的概念指针的概念一个变量在内存中所占存储单元的地址号就是该变量的指针。如:inti;i=20;假设i变量在内存中所占存储单元的地址号为:1000,此时

162、称1000这个存储地址为变量i的指针,而20是变量i的值。2.8.1.1 指针指针变量变量的定义的定义专门存放其他变量地址的变量称为指指针针变变量量。和其他变量的定义类似,指针变量在使用前也必须定义其类型。其定义的一般形式为:类型标识符号*指针变量名表如:inti=50;int*ip;说明:(1)指针变量名前面的*表示该变量为指针变量,它不是变量名本身的一部分。(2)此处的类型标识符是该指针变量所要指向的变量的类型。207返回返回 2.8 2.8 指针类型及使用指针类型及使用(3)变量的指针和指向变量的指针变量的区分:指针是某一变量在内存中所占存储单元的地址,是一个地址值。而指针变量则是专门存

163、放其他变量的地址的变量,是个变量,如果某一指针变量中存放了另外一个变量的指针,则称该指针变量是指向指向那个变量的指针变量。2.8.1.2 与指针运算有关系的两个运算符与指针运算有关系的两个运算符1. &:求某一变量所占存储单元的存储地址。如:inti=50;int*ip;ip=&i;/&i求变量i的存储单元的地址(即指针)此时,指针变量ip存放了变量i的存储地址(指针),因此称指针变量ip此时是指向变量i的。208返回返回 2.8 2.8 指针类型及使用指针类型及使用2. *:取出指针变量所指向的变量的内容,后面跟指针变量。如:*ip为取出指针变量所指向的变量的内容。即由于ip是指向变量i的,

164、所以*ip与i是等价的。2.8.1.3 指针变量的引用指针变量的引用指针变量的引用,即使用指针变量,其使用方法和普通变量的使用原理一致,但要注意:(1)指针变量是一个变量:一一个个指指针针变变量量和和普普通通变变量量一一样样,在在内内存存中中也也占占存存储储单单元元,因此一个指针变量也相当于一个容器,所以指指针针变变量量也也有有其其指指针针,这这就就是是指指针针变变量的指针量的指针。209返回返回 2.8 2.8 指针类型及使用指针类型及使用(2)指针变量内只只能能存存放放其其他他变变量量的的地地址址,而而不不能能直直接存放一个普通数据接存放一个普通数据。(3)一个指针变量只能指向同一个类型的

165、变量,如上例中指针变量ip只能总是指向整型变量。(4)一个指针变量只有先先指指向向某某一一个个变变量量后后,才才可可利利用该指针变量对它所指向的变量进行操作(间接访问用该指针变量对它所指向的变量进行操作(间接访问)。【例例2-15】指针变量及其使用方法。#includevoidmain(void)210返回返回 2.8 2.8 指针类型及使用指针类型及使用inta,b;int*ip1,*ip2;/定义了两个指向整型的指针变量。a=100;b=100;ip1=&a;ip2=&b; /将 变 量 a,b的 地 址 赋 给 两 个 拂 针 变 量 , /这时,指针变量ip1指向变量a,而ip2指向b

166、coutabendl;cout*ip1*ip2endl;/等价于coutabendl;*ip1=200;/等价于a=200;*ip2=300;/等价于b=300;cout*ip1*ip2endl;(指针的算术运算.cpp)211返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.2 const指针指针1指向常量的指针变量的定义与使用指向常量的指针变量的定义与使用const类型标识符*指针变量名;如:constint*p;用这种方法定义的指针变量,借助该指针变量只可读只可读取它所指向的变量或常量的值,但不可借助该指针变量取它所指向的变量或常量的值,但不可借助该指针变量对其所指向的对象的

167、值进行修改(即重新赋值)对其所指向的对象的值进行修改(即重新赋值)。但是,可允许这种指针变量指向另外一个同类型的别的变量允许这种指针变量指向另外一个同类型的别的变量。如:212返回返回 2.8 2.8 指针类型及使用指针类型及使用includevoidmain(void)constinti=20;intk=40;constint*p;/定义指向常量的指针变量pp=&i;/指针变量p指向变量icout*pi;*p=100;/该句错误,不可借助p对它所指向的目标进行重新赋值p=&k;/可以使p指向另外一个同类型的变量cout*pk;*p=200;/该句错误k=200;213返回返回 2.8 2.8

168、 指针类型及使用指针类型及使用2指针常量指针常量指针常量的定义格式为:类型标识符*const指针变量名=初始指针值;如:char*constp=”abcde”用该种方法定义的指指针针变变量量,其其值值(是是一一个个指指针针值值),不不可可进进行行修修改改,但但可可以以借借助助该该指指针针变变量量对对其其所所指指向向的的对对象象的的值值进进行行读读取取或或修修改改。另另外外,这这种种指指针在定义时必须初始化针在定义时必须初始化。如:214返回返回 2.8 2.8 指针类型及使用指针类型及使用#includeiostream.hvoidmain(void)chars=askdfsljfl;char

169、*constp=s;/必须初始化/p=xyz/该句错误,不可再使指针变量指/向另外一个地址(指针)cout*p;*p=s;cout*p;/p+;/error*p=q;cout*p;215返回返回 2.8 2.8 指针类型及使用指针类型及使用3. 指向常量的指针常量指向常量的指针常量指向常量的指针常量的定义方法为:const类型标识符*const指针变量名=初始指针值;如:intb;constint*constp=&b;用这种方法定义的变量,既不不允允许许修修改改指指针针变变量量的的值值,也也不不允允许许借借助助该该指指针针变变量量对对其其所所指指向向的的对对象象的的值值进进行行修修改改。另另外

170、外,该该变变量量在在定定义义时时必必须须初始化初始化。如:216返回返回 2.8 2.8 指针类型及使用指针类型及使用voidmain(void)inta=10;intc=30;constintb=20;constint*constp=&a;constint*constq=&b;p=&c;/错误*p=50;/错误217返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.3 指针与函数指针与函数前面讲过,函数的参数可以为整型、实型、字符型等普通变量。实参与形参间参数的传递是单向的“值传递”。但函函数数的的参参数数也也可可为为指指针针,它的作用是将一个变量的地址传给被调函数的形参。此时主

171、调函数的调用点上的实参必须是地址值(指针),而被调函数的形参一定要定义成指针变量的形式此时,被调函数的形参得到的是实参的指针,因此,该该形形参参变变量量就就指指向向实实参参,在在被被调调函函数数中中对对形形参参的的操操作作就就相相当当于于对对它所指向的实参的操作它所指向的实参的操作。218返回返回 2.8 2.8 指针类型及使用指针类型及使用【例例2-16】交换两个变量的值。#includevoidswap(int*p1,int*p2)/形参p1和p2的要定义成指 /针变量形式intp;p=*p1;*p1=*p2;*p2=p;voidmain(void)inta,b;cinab;swap(&a

172、,&b);/以变量a和变量b的地址作为实参值。couta,ab;c=max(a,b);couty)z=x;elsez=y;return(z);221返回返回 2.8 2.8 指针类型及使用指针类型及使用如果改用指向函数的指针变量的话,则main函数为:voidmain(void)int(*p)(int,int);/定义了一个指向返回值为int型,带两个int参数的 /函数的指针变量pinta,b,c;p=max;/将函数max的首地址(即指针)赋 /给指针变量pcinab;c=(*p)(a,b);/orc=p(a,b);coutc;222返回返回 2.8 2.8 指针类型及使用指针类型及使用说

173、明:(1)int(*p)(int,int)说明了一个指向返回值为整型,带两个整型参数的函数的指针。(2)p=max表示把函数的入口地址赋给指针变量p,那么*p就是函数max.因此c=(*p)(a,b);或c=p(a,b);和c=max(a,b)等价。注意:(1)函数的调用可以通过函数名调用,也可通过函数指针调用可通过函数指针调用。(2)int(*p)(int,int);只是表示定义了一个指向函数的指针变量。(3)在函数指针变量赋值时,只须给出函数名,不必给出参数:如:p=max;因为只是传递函数的地址。(4)对指向函数的指针做象p+n,p+,p等算数运算是无意义的。223返回返回 2.8 2.

174、8 指针类型及使用指针类型及使用2.8.3.2 把指向函数的指针变量作函数参数把指向函数的指针变量作函数参数函数的指针变量主要的用途就是把指针作为参数传递到其它函数。如:(例 函数指针作为函数的参数例1.cpp 函数指针.cpp 指向函数指针作为函数的参数例2.cpp pointer_to_pointer1.cpp pointer_to_pointer2.cpp pointeranddimension.cpp pointererror.cpp 函数指针数组和二级函数指针.cpp 关于动态内存分配)224返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.3.3 返回指针值的函数返回指

175、针值的函数返回指针值的函数的定义方式为:类型标识符号*函数名(参数名)如:int*fun(intx,inty)此时,该函数体内的return语句的形式为:return(指针值);/例返回指针1.cpp返回指针2.cpp返回指针3.cpp225返回返回 【例例】 定义findmax()函数,其功能是寻找数组中的最大元素,将该元素的下标通过参数返回,并返回其地址值,编程实现findmax()函数。#includeiostream.hint*findmax(int*array,intsize,int*index);voidmain(void)inta=33,91,54,67,82,37,85,63,

176、19,68;int*maxaddr;intidx;maxaddr=findmax(a,sizeof(a)/sizeof(*a),&idx);coutidxendl;coutmaxaddrendl;coutaidxendl;int*findmax(int*array,intsize,int*index)intmax,i;max=*(array+0);/array0;for(i=1;isize;i+)if(max*(array+i)max=*(array+i);*index=i;return(array+*index);226返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.4 指针与

177、数组指针与数组数组的指针即整个数组在内存中的起始地址;数组元素的指针是数组中某一元素所占存储单元的地址。引用数组元素时是利用数组的下标进行的,也可以利用指针来进行,利用指针引用某一数组元素时,即可以先使一指针变量指向某一数组元素,然后通过该指针变量对它所指向的数组元素进行操作。2.8.4.1 指向数组元素的指针变量的定义与赋值指向数组元素的指针变量的定义与赋值指向数组元素的指针变量的定义与以前定义指针变量的方法相同,只要注意指针变量定义时的类型要与所要指向的数组的类型一致即可。227返回返回 2.8 2.8 指针类型及使用指针类型及使用如:inta10;int*p;p=&a0;/把数组元素a0

178、的地址赋给指针变量p。C+语言中规定:数组名就代表数组首地址。也就是数组第0号元素的地址。如:inta10;int*p;p=&a0;/*与p=a;是等价的*/p=&a0;与p=a;是等价的。但要注意,其作用是把数组a的起始地址赋给指针变量p,而不是把数组a的各元素的地址赋给p。228返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.4.2 通过指针变量使用数组元素通过指针变量使用数组元素假设p为指向某一数组元素的指针变量。C+语言规定:p+1指向数组的下一个元素。(注意不是单纯的p加1)。设定义了一个数组a10,p的初值为&a0,即此时p指向a0元素,则:(1)p+1或a+1就是a

179、1元素的存储地址,即它们都指向数组的第1号元素a1。所以*(p+1)或*(a+1)就与a1是等价的。/指针变量的下标元素.cpp(2)p+i或a+i就是ai元素的存储地址,即它们都指向数组的第i号元素ai。所以*(p+i)或*(a+i)就与ai是等价的。因此,利用此方法就可访问到数组元素。如:229返回返回 2.8 2.8 指针类型及使用指针类型及使用#include”iostream.h”voidmain(void)inta10;int*p,i;for(i=0;iai;p=a;for(i=0;i10;i+)cout*(p+i);/等价于coutai;或coutpi;230返回返回 2.8 2

180、.8 指针类型及使用指针类型及使用对以上讲过的内容再作几点补充说明:假设已定义了一个数组a10,且定义了一个指针变量p,赋初值a.即p=a;,则:(1)p+是指向数组元素的下一个元素;即:a1。(2)*p+的运算,*p+等同于*(p+),它的作用是先得到p所指向的元素的值(即*p),然后再使p+1。如:for(i=0;i10;i+,p+)cout*p+;(3)*(p+)与*(+p)的作用是不同的。*(p+)是先取p的值作*运算,然后再使p加1(即指向下一个元素);*(+p)是先使p加1(即使p指向下一个元素),然后再作*运算。231返回返回 2.8 2.8 指针类型及使用指针类型及使用如:若p

181、的初值为a,(即&a0),输出*(p+)时,得到a0的值,而输出*(+p),则得到a1的值。(4)(*p)+表示p所指的元素值加1,对上例来说a0+。(5)对于指针的-(自减)运算原理同上。(6)只有指向数组元素的指针变量才可进行自加或自减运算。/例指针与数组及自增运算符.cpp/二维数组中的最大最小元素及位置.cpp/二维数组与指针的关系.cpp232返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.4.3 数组名作函数参数数组名作函数参数数组名可以用来作为实参和形参。用数组名作实参,在调用函数时实际上是把把数数组组的的首首地地址址传传递递给给形形参参,这样,实实参参数数组组就就

182、与与形形参参数数组组共共占占同同一一段段内内存存,那么形参数组中元素的值发生变化后,实参数组中各元素的值也发生变化,但这种变化并不是从形参传回实参的,而是由于形参与实参数共享同一段内存而造成的.233返回返回 2.8 2.8 指针类型及使用指针类型及使用利用数组名作为函数的参数时可以用以下四种情况实现:(1)形参和实参都用数组名(2)实参用数组名,形参用指针变量(3)实参和形参都用指针变量(4)实参用指针变量,形参用数组名【例例2-19】函数func是实现数组排序的过程。主函数将8个整数读入,调用func排序并输出结果。#includevoidfunc(int*);/func的函数原型void

183、main(void)234返回返回 2.8 2.8 指针类型及使用指针类型及使用intdata8;inti;coutn输入8个数:;for(i=0;idatai;func(data);/注意实参的写法coutn排序输出:;for(i=0;i8;i+)coutdatai,;coutendlendl;235返回返回 2.8 2.8 指针类型及使用指针类型及使用voidfunc(int*s)/注意形参类型inti,j;intwork;for(i=0;i8;i+)for(j=i+1;j8;j+)if(*(s+i)*(s+j)/从大到小排序(选择)work=*(s+i);*(s+i)=*(s+j);*(

184、s+j)=work;236返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.5 指针与字符串指针与字符串2.8.5.1 字符串的指针和指向符串的指针变量字符串的指针和指向符串的指针变量字符串在内存中的首地址称字符串的指针字符串的指针在c+程序中,可以用两种方法来实现字符串的保存:(1)用字符数组来实现(2)用字符串指针实现如:voidmain(void)char*string=”clanguage”;coutstring;/or:cout&string0;输出结果:clanguage注意:输出时的指针变量的写法是string而不是*string。237返回返回 2.8 2.8 指针

185、类型及使用指针类型及使用当显示字符的指针时,这个指针显示字符串而不是指针的内容。因为C格式的字符串是通过字符的指针定义的。这个问题的解决方案很简单;要在字符指针中显示地址,我们只需要把它强制转换为void指针。/显示字符指针的值.cpp/指针的大小.cpp/指针的兼容性.cpp238返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.5.2 字符串指针作函数参数字符串指针作函数参数可以采用以下4种方法:实参形参(1)数组名数组名(2)数组名字符指针变量(3)字符指针变量 字符指针变量(4)字符指针变量 数组名【例例2-20】将字符串a复制为字符串b。239返回返回 2.8 2.8 指

186、针类型及使用指针类型及使用#includevoidcopy_string(char*to,char*from)for(;*from!=0;from+,to+)*to=*from;*to=0;voidmain(void)chara20=clanguage;charb20=verygood;copy_string(a,b);coutaendl;coutbendl;240返回返回 补充补充-string -string 类类使用数组来存放字符串,调用系统函数来处理字符串,显得不是很方便,而且数据与处理数据的函数分离也不符合面向对象方法的要求。为此,C+标准库将面向对象的串的概念加入到C+语言中,预定

187、义了字符串(string类)。string类提供了对字符串进行处理所需要的操作。使用string类需要包括头文件string。string类封装了串的属性并提供了一系列允许访问这些属性的服务,属性或类的数据组件包括:字符序列(sequenceofcharacters)字符序列的大小或长度(sizeorlengthofthesequenceofcharacters)序列中字符的类型字符的特点(charactertraits)241返回返回 补充补充-string -string 类类一个字符的大小分配算符(allocator)迭代子(iterators)串类也描述了很多有关串操作的服务,包括:查

188、找(search)分配(assign)连接(concatenate)追加(append)这里我们简要介绍一下string类的构造函数、几个常用的成员函数和操作。为了简明起见,函数原型是经过简化的,与头文件中的形式不完全一样。大家如果需要详细了解,可以查看编译系统的联机帮助。242返回返回 补充补充-string -string 类类(1)构造函数的原型string();/默认构造函数,建立一个长度为0的串string(conststring&rhs);/拷贝初始化构造函数string(conststring&rhs,unsignedintpos,unsignedintn);/将对象rhs中的串

189、从位置pos开始取n个字符,用来初始化string类的对象。串中的第一个字符位置为0string(constchar*s,unsignedintn);/用指针s所指向的字符串中的前n个字符初始化string类的对象string(unsignedintn,charc);/将参数c中的字符重复n次,用来初始化string类的对象243返回返回 补充补充-string -string 类类/字符串类构造函数.cpp(2)常用成员函数功能简介stringappend(constchar*s);/将字符串s添加在本串尾stringassign(constchar*s);/赋值,将s所指向的字符串赋值给本

190、对象intcompare(conststring&str)const;/比较本串与str中串的大小,当本串str串时,返回正数,两串相等时,返回0string&insert(unsignedintp0,constchar*s);/将s所指向的字符串插入在本串中位置po之前244返回返回 补充补充-string -string 类类stringsubstr(unsignedintpos,unsignedintn)const;/取子串,取本串中位置pos开始的n个字符,构成新的string类对象作为返回值unsignedintfind(constbasic_string&str)const;/查找

191、并返回str在本串中第一次出现的位置/例string类的常用成员函数.cpp245返回返回 补充补充-string -string 类类unsignedintlength()const;/返回串的长度(字符个数)voidswap(string&str);/将本串与str中的字符串进行交换(3)string类的操作符下表列出了string类的操作符及其说明操作符示例注释+s+t将串s和t连接成一个新串=s=t用t更新s+=s+=t等价于s=s+t=s=t判断s与t是否相等!=s!=t判断s与t是否不等246返回返回 操作符示例注释st判断s是否小于t=sst判断s是否大于t=s=t判断s是否大于

192、或等于tsi访问串中下标为i的字符补充补充-string -string 类类/一个string类应用的例子.cpp/串的比较.cpp/C串的操作.cpp/string类字符串的操作.cpp/字符串的输入和输出.cpp/string串的输入输出.cpp/getline与get区别.cpp/整行读入再分解各个数据.cpp/分解单词.cpp247返回返回 补充补充- -向量向量P873.6向量(Vectors)1.基本操作(BasicOperations)vector是向量类型,它是一种对象实体,具有值,所以可以看做是变量。它可以容纳许多其他相同类型的实体。如若干个整数,所以称其为容器。Vecto

193、r是C+STL(标准模板类库)的重要一员,使用它时,只要包含头文件vector即可。vector可以有四种定义方式:(1)vectora(10);248返回返回 补充补充- -向量向量(2)vectorb(10,1);(3)vectorc(b);(4)vectord(b.begin(),b.begin()+3);vector是模板形式,尖括号中为元素类型名,它可以是任何合法的数据类型。第1种形式定义了10个整数元素的向量,但没有给出初值,因而,其值是不确定的。第2种形式定义了10个整数元素的向量,且给出其每个元素的初值为1.这种形式是数组望尘莫及的。数组只能通过循环来成批地赋给相同初值。249

194、返回返回 补充补充- -向量向量第3种形式用另一个现成的向量来创建一个向量。第4种形式定义了其值依次为b向量中第0到第2个(共3个)元素的向量。b.begin()、b.end()是表示向量的起始元素位置和最有一个元素之外的元素位置。向量元素位置也属于一种类型,称为遍历器。遍历器不单表示元素位置,还可以在容器中前后挪动。每种容器都有对应的遍历器。向量中的遍历器类型为:vector:iterator。250返回返回 补充补充- -向量向量因此,如果要输出向量中所有元素,可以有两种循环控制方式:(1)for(inti=0;ia.size();i+)coutai“;(2)for(vector:iter

195、atorit=a.begin();it!=a.end();+it)cout*it“;a.size()是向量中元素的个数,a.begin()表示向量的第一个元素。向量中的操作都是通过使用成员函数来完成的。它的常用操作有:251返回返回 补充补充- -向量向量a.assign(b.begin(),b.begin()+3);/b向量的02个元素构成向量赋给aa.assign(4,2);/使a向量只含03元素(4个元素),且赋为值2intx=a.back();/将a向量的最后一个向量元素值赋给整数变量xa.clear();/a向量中元素清空(不再有元素)if(a.empty()cout“empty”;

196、/判断向量空否252返回返回 补充补充- -向量向量inty=a.front();/将a的第一个向量元素值赋给变量ya.pop_back();/删除a向量的最后一个元素a.push_back(5);/在a向量最后插入一个元素,其值为5a.resize(10);/将向量元素个数调至10个,多则删,少则增/补,其值随机a.resize(10,2);/将向量元素个数调至10个,多则删,少则/增补,其值为2if(a=b)cout“equal”;/向量的比较操作还有:!=、/、=除此之外,还有元素的插入与删除、保留元素个数、容量观察等操作,请参看NicolaiM.Iosuttis.C+标准程序库自修教程

197、与参考手册。侯捷,孟岩译,华中科大出版社,2002.另外,向量还可以从数组获得初值。例如:另外,向量还可以从数组获得初值。例如:inta7=1,2,5,3,7,9,8;vectorva(a,a+7);253返回返回 补充补充- -向量向量另外,向量还可以从数组获得初值,如:inta7=1,2,5,3,7,9,8;vectorva(a,a+7);/向量操作1.cpp/向量操作2.cpp/向量操作3.cpp/二维向量操作.cppp89254返回返回 2.8 2.8 指针类型及使用指针类型及使用2.8.6 指针数组和指向指针的指针指针数组和指向指针的指针.1. 指针数组指针数组如果一个数组中的元素均

198、为指针类型的数据,则称这个数组为指针数组。其定义方式为:类型标识符类型标识符 * 数组名数组名数组长度数组长度 如:int*p4;/注意:int(*p)4;p为一个指向具有4个/整型元素的一维数组的指针(例指向一维数组的指针.cpp 指向二维数组的指针.cpp)这种指针数组比较适合于处理字符串。如:char*name3=“fortran”,”basic”,”pascal”;(例:指针数组例1.cpp)2. 指向指针的指针指向指针的指针.前面已经介绍过指针数组.255返回返回 2.8 2.8 指针类型及使用指针类型及使用如:char*name3说明该数组中的元素都是指针,数组代表了该指针数组的起

199、始地址,name是指向指针型数据的指针。定义指向指针的指针变量的方式为:类型标识符号类型标识符号 *变量名变量名如:char*p;*p相当于*(*p),说明指针变量p是指向一个字符指针变量(指向字符型数据的指针变量)的。(例:pointer_to_pointer2.cpp 指针数组例2.cpp指针与数组及字符串的关系.cpp指向指针的指针示例.cpp)256返回返回 补充:main()的变元argc和argv(命令行参数) 有时,需要向程序传入信息。我们一般 通过命令行向主函数main()传递信息。命令行变元(command line argument)是操作系统命令行中,执行程序名字之后的信

200、息。例如,在UNIX系统下编译C程序时,在提示符下键入类似下行的内容。 cc program_name 其中,program_name是准备被编译的程序。程序名字program_name作为参数传给命令cc(编译程序)。 类似地,C+的源程序经编译、链接后生成了可执行的程序(如:myprogram.exe)后,允许向该程序传送参数,形式为D:msmyprogram para1 para2 paraN 257返回返回 main(int argc,char *argv)函数中的两个参数用于接受运行程序时命令行传入的参数信息,一个是argc,另一个是argv。 argc是整型变量,用于存放命令行中参

201、数的总数(因为程序名也计算在内,argc的值最小为1)。 形参argv是一个指针数组,指针数组中的每个元素(是一个指针)都分别指向相应的一个命令行变元(字符串)。 如:D:myprogram para1 para2 para3则argc值为4,指针argv0指向命令行参数myprogram(即程序名),指针argv1指向命令行参数para1,指针argv2指向命令行参数para2,指针argv3指向命令行参数para3。(例 aboutmain.cpp)/程序设计其他问题面试题.cpp258返回返回 2.9 期末考试考试知识点期末考试考试知识点1 理解常用的基本数据类型理解常用的基本数据类型各

202、种基本数据类型的常量和变量的使用;各种基本数据类型的常量和变量的使用;2 2 各种常见的运算符及其构成的表达式各种常见的运算符及其构成的表达式算术(特别注意算术(特别注意+a+a和和a+)a+),关系,条件(问号),逗号。关系,条件(问号),逗号。3 3 各种控制语句的含义和使用各种控制语句的含义和使用for,while,dowhile,switch4 4 函数函数理解函数,函数的定义,函数的参数类型(传值参数、传地址指针参数,引用参数),函数原型的使用,递归函数的理解和使用,内联函数、重载函数及带默认参数的函数的基本含义及注意点,变量的各种存储类型(局部变量、全局变量、静态局部变量和静态全局

203、变量等)5 5 数组(一种结构类型)及其使用数组(一种结构类型)及其使用数组的概念,定义方法,初始化方法,数组的使用(注意熟悉对数组元素的排序算法),数组作为函数的参数(传地址)的使用方法。259返回返回 2.9期末考试考试知识点期末考试考试知识点6 6 指针指针 理解指针这种数据类型(另一种结构类型)的含义,指针类型变量的定义和使用(注意指针类型变量的初始化),指针变量q可以指向另一个指针类型的变量p(二级指针的使用),指针变量m可以指向函数(m的声明,可以通过指针变量m调用它所指向的函数),指针与数组(特别是字符数组)的关系(通过指针访问该数组的各元素),三种特殊的指针(const int

204、 *p,int * const p和const int * const p)的含义,指向相同基类型的多个指针可以构成数组(指针数组)(注意和指向数组的指针的不同声明方式:int *p4;int (*p)4),函数可以返回指针类型,动态内存的分配((int *)malloc(80*sizeof(int)和new int 80等,#include”stdlib.h”) 260返回返回 2.9期末考试考试知识点期末考试考试知识点7 7 可以借助讲稿中和课本中的例子来复习这些知可以借助讲稿中和课本中的例子来复习这些知识点识点8 8 微软总裁比尔微软总裁比尔. .盖茨的做事标准:盖茨的做事标准:Its

205、fun!Its fun! 工作如此,学习也应当如此,只有把学习当成一种乐趣,才能学有所成! 把这句话送给大家。相信大家期末可以考出自己满意的成绩。也希望每个同学都可以有望成为一个“E学生”:第一,很高的情商(Quotient);第二,快乐,享受学习,而不仅仅是完成学习(Enjoy);第三,优秀,杰出(Excellence)。261返回返回 2.9 引用引用2.9.1 引用的概念、声明和使用引用的概念、声明和使用1引用及声明方法引用及声明方法引用就是某一变量(目标)的一个别名,这样对引用的操作就是对目标的操作。引用的声明方法:类型标识符类型标识符 &引用名引用名=目标变量名;目标变量名;如:in

206、ta;int&ra=a;/定义引用ra,它是变量a的引用,即别名说明:(1)&在此不是求地址运算,而是起标识作用。(2)类型标识符是指目标变量的类型。(3)声明引用时,必须同时对其进行初始化声明引用时,必须同时对其进行初始化。262返回返回 2.9 引用引用(4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名。(5)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,所以系统并不给引系统并不给引用分配存储单元。用分配存储单元。2引用的使用引用的使用(1)一旦一个引用被声明,则该引用名就只能作为目标变量名的一个别名来使用,所以不能再把该引用名作为不能再

207、把该引用名作为其他变量名的别名其他变量名的别名,任何对该引用的赋值就是该引用对应的目标变量名的赋值。(2)对引用求地址,就是对目标变量求地址。263返回返回 2.9 引用引用【例例2-21】 引用的定义及使用方法。#includevoidmain()inta,b=10;int&ra=a;/定义引用ra,初始化成变量a,所以ra是 /变量a的引用(别名)a=20;coutaendl;coutraendl;/等价于coutaendl;cout&aendl;/输出变量a所占存储单元的地址 cout&raendl;/等价于cout&aendl;264返回返回 2.9 引用引用ra=b;/等价于a=b;

208、coutaendl;coutraendl;/等价于coutaendl;coutbendl;cout&aendl;cout&raendl;/等价于cout&aendl;cout&bendl;(3)由于指针变量也是变量,所以,可以声明一个指针变量的引用。方法是:类型标识符类型标识符 *&引用名引用名=指针变量名;指针变量名;265返回返回 2.9 引用引用如:#includevoidmain(void)int*a;/定义指针变量aint*&p=a;/定义引用p,初始化为指针变量a,所以p是/a的引用(别名)intb=10;p=&b;/等价于a=&b,即将变量b的地址赋给a。cout*aendl;/

209、输出变量b的值cout*pendl;/等价于coutab;/输入a,b两变量的值swap(a,b);/直接以变量a和b作为实参调用swap函数coutaab;swap(&a,&b);/必须以变量a和b的地址作为实参coutab;273返回返回 2.9.3 如何使一个被调函数同时返回多个值如何使一个被调函数同时返回多个值由于函数的返回值是通过函数体中的return语句完成的,但一个return语句只能返回一个值,为此,我们可以采用以下方法:(1)利用全局变量的方法:可以在程序的开头定义一些全局变量。这样,当被调函数执行完毕后,所需要的数据已保存在了全局变量中,在主调函数中直接读取全局变量的值即可

210、。(2)使用指针或数组的方法:因为在指针作为函数参数的情况下,可将主调函数的某些变量的地址传递给被调函数。2.9 引用引用274返回返回 (3)利用引用的方法:通过前面的学习,我们知道,使用引用传递参数,可以在被调函数中改变主调函数中目标变量的值,这种方法实际上就是可以使被调函数返回多个值。【例例2-22】 使用引用使函数返回多个值。以下定义了可以同时返回10个数中的最大值和最小值的函数max_min。2.9 引用引用275返回返回 #includevoidmax_min(int*p,intn,int&max,int&min);/声明函数max_minvoidmain(void)inta10;

211、intma,mi;inti;for(i=0;iai;max_min(a,10,ma,mi);/调用函数max_mincoutmami;2.9 引用引用276返回返回 2.9 引用引用voidmax_min(int*p,intn,int&max,int&min)/形参max和min定义成引用inti=0;max=*(p+i);min=*(p+i);for(i=1;in;i+)if(max*(p+i)min=*(p+i);/实质上就是对实参变量mi赋值277返回返回 2.9.4 用引用返回函数值用引用返回函数值要以引用返回函数值,则函数定义时要按以下格式:类型标识符类型标识符 &函数名(形参列表及

212、类型说明)函数名(形参列表及类型说明)函数体函数体说明:(1)以引用返回函数值,定义函数时需要在函数名前加&(2)用引用返回一个函数值的最大好处好处是,在内存中不产生被返回值的副本。【例例2-23】以下程序中定义了一个普通的函数fn1(它用返回值的方法返回函数值),另外一个函数fn2,它以引用的方法返回函数值。2.9 引用引用278返回返回 #includefloattemp;/定义全局变量tempfloatfn1(floatr);/声明函数fn1float&fn2(floatr);/声明函数fn2floatfn1(floatr)/定义函数fn1,它以返回值的方法返回/函数值temp=(flo

213、at)(r*r*3.14);returntemp;float&fn2(floatr)/定义函数fn2,它以引用方式返回函数值temp=(float)(r*r*3.14);returntemp;2.9 引用引用279返回返回 voidmain(void)/主函数floata=fn1(10.0);/第1种情况,系统生成要返回值的/副本(即临时变量)float&b=fn1(10.0);/第2种情况,可能会出错出错(不同/C+系统有不同规定)/不能从被调函数中返回一个临时变量或局部变量的引用不能从被调函数中返回一个临时变量或局部变量的引用/(值方式返回时复制(值方式返回时复制temp的值给临时变量,返

214、回到主函数后,引用的值给临时变量,返回到主函数后,引用b /以该以该临时变量初始化,使得临时变量初始化,使得b成为临时变量的别名。可这样:成为临时变量的别名。可这样: /int x=fn1(10.0); int& b=x;p194)floatc=fn2(10.0);/第3种情况,系统不生成返回值的副本.c直接从变量/temp中得到复制。float&d=fn2(10.0);/第4种情况,系统不生成返回值的副本/可以从被调函数中返回一个全局变量的引用coutacd;2.9 引用引用280返回返回 2.9 引用引用2.9.5 一个返回引用的函数值作为赋值表达式的左值一个返回引用的函数值作为赋值表达式

215、的左值一般情况下,赋值表达式的左边只能是变量名,即被赋值的对象必须是变量,只有变量才能被赋值,常量或表达式不能被赋值,但如果一个函数的返回值是引用时,如果一个函数的返回值是引用时,赋值号的左边可以是该函数的调用赋值号的左边可以是该函数的调用。【例例2-24】 测试用返回引用的函数值作为赋值表达式的左值。#includeint&put(intn);intvals10;interror=-1;voidmain()281返回返回 2.9 引用引用put(0)=10;/以put(0)函数值作为左值,等价于/vals0=10;put(9)=20;/以put(9)函数值作为左值,等价于/vals9=20;

216、coutvals0;cout=0&n=9)returnvalsn;elsecout”subscripterror”;returnerror;282返回返回 2.9 引用引用2.9.6 用用const限定引用限定引用声明方式:const 类型标识符类型标识符 &引用名引用名=目标变量名;目标变量名;用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为使引用的目标成为const,达到了引用的安全性。注意:C+中,不能给引用本身重新赋值,使它指向另一个变量,因此引用总是const的。如:inta=100,b=200;int&ra=a;int&ra=b;/error:rede

217、finition;differenttypemodifiers【例例2-25】283返回返回 2.9 引用引用#include“iostream.h”double&fn(constdouble&pd)staticdoublead=32;ad+=pd;coutpdendl;returnad;voidmain(void)doublea=100.0;double&pa=fn(a);coutpaendl;a=200.0;pa=fn(a);coutpaendl;程序运行的结果为:100132200332284返回返回 2.9 引用引用2.9.7 引用总结引用总结(1)在引用的使用中,单纯给某个变量取个别

218、名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大对象的传递效率和空间不如意的问题。(2)用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。(3)引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作,程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。(例:p2029.1:p202_1_1.cpp,p202_1_23.cpp)285返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2.10.1 结构体结构体数组中的各元素是属于同一类型的,但有

219、时需要将不同类型的数据组合成一个有机的整体,并且这些数据是相互联系的,这就引出了结构体。结构体是由由多多种种类类型型的的数数据据组组成成的的整整体体。组成结构体的各个分量称为结构体的数据成员(简称成员)。2.10.1.1 定义结构体定义结构体定义结构体的一般格式为:struct 结构体名结构体名 成员列表成员列表 变量名列表;变量名列表;286返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举结构体定义是以关键字struct开始的,结构体名应是有效的C+标识符。结构体中的每个成员都必须通过定义来确定成员名及其类型。例如:structstudentintnum;/学号charname2

220、0;/姓名charsex;/性别intage;/年龄student1;其中,student是定义的结构体名,该结构体有四个成员变量num、name、sex、age。student1是定义的结构体变量。结构必须至少包含一个成员。287返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举也可以在结构体定义后再定义结构体变量可以在结构体定义后再定义结构体变量。格式是:struct结构体名变量名列表;如:structstudentintnum;/学号charname20;/姓名charsex;/性别intage;/年龄;structstudentstudent1;studentstudent1

221、;288返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2.10.1.2 结构体变量的初始化结构体变量的初始化结构体变量的初始化就是在定义结构体变量的同时,为其成员提供初值,可采用以下两种方法:(1)在定义结构体类型的同时,为结构体变量初始化。 struct 结构体名结构体名 成员列表成员列表 变量名变量名=初始值列表初始值列表;如:structstudentintnum;/学号charname20;/姓名charsex;/性别intage;/年龄student1=9901,wang,f,23;289返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举(2)利用已有的结构体

222、类型定义结构体变量,并同时初始化。格式是: 结构体名称结构体名称 变量名变量名=值值1,值,值2,;如:studentstu=1,”zhang”,M,20,90.0;此时,student1变量中的num成员的值为9901,name成员的值为wang,sex成员的值为23。2.10.1.3 结构体变量的引用结构体变量的引用定义了结构体变量以后,就可以在程序中使用这些变量。引用结构体变量时应注意:(1)不不能能将将结结构构体体变变量量作作为为一一个个整整体体来来引引用用,只只能能引引用用结构体变量中的成员结构体变量中的成员。引用结构体变量中成员的格式为: 结构体变量名结构体变量名.成员名成员名29

223、0返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举如:coutstudent1.name;此处的“.”是成员运算符,它的优先级别最高。(2)若结构体的成员本身又是一个结构体变量,则要使用多个成员运算符,一级一级地找到最低一级的成员进行引用。(3)对结构体成员变量的使用可像普通那样进行,如:进行赋值,参加运算等。如:structstudents1,s2;s1.num=9901;s2.num=s1.num+1;291返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举(4)可以将一个已有值的结构体变量的值直接赋给另外一个相同类型的结构体变量。方法是:结构体变量名结构体变量名1=

224、结构体变量名结构体变量名2;如:studentst1=1,”zhang”,M,20,90.0;studentst2;st2=st1;(5)可以引用成员的地址。也可以引用结构体变量的地址。如:&student.num&st1/结构体类型的应用-顺序表的逆置操作.cpp292返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2.10.1.4 结构数组结构数组结构数组:即数据类型为结构体类型的数组,这样,数组中的每个元素都属于同一种结构体类型,每一元素都分别包含了结构体中的每个成员。1. 结构数组的定义结构数组的定义structstudentintnum;charname20;intage

225、;floatscore;charaddr30;studentstu3;293返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举这就定义了一个结构数组stu,它已含三个元素,其中每个元素都为student类型,且每个数组元素都各自拥有自己的一套结构成员num、name、age、score和addr。2结构体数组的初始化结构体数组的初始化结构体数组在定义时也可以进行初始化。其初始化方法与一般数组的初始化方法基本相同,只是必须为每个元素提供各结构成员的值,如:structstudentintnum;charname20;charsex;294返回返回 2.10 结构体、共用体和枚举结构体、

226、共用体和枚举intage;studentstu3=1,sum1,M,20,2,zhao2,M,25,3,qian3,M,21;2.10.1.5指向结构体类型的指针指向结构体类型的指针1. 指向结构体变量的指针指向结构体变量的指针结构体变量的指针:是指结构体变量所占内存单元的起始地址。因此,可以定义指指针针变变量量指指向向结结构构体体变变量量。此时该指针变量的值就是结构体变量在内存中起始地址该指针变量的值就是结构体变量在内存中起始地址。【例例2-26】指向结构体变量的指针的使用。295返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举#includeiostream.h#include

227、string.hvoidmain()structstudent/定义结构体类型studentlongintnum;charname20;charsex;floatscore;studentstu1;/定义结构体类型student的变量stu1student*p;/定义student类型的指针变量pp=&stu1;/将结构体变量stu1的地址赋给指针变量pstu1.num=1;/分 别 给 结 构 体 变 量 stu1的 num、 name、 /sex、score成员赋值296返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举strcpy(stu1.name,lilin);stu1.s

228、ex=M;stu1.score=89;/输出stu1各成员的值coutstu1.numtstu1.nametstu1.sextstu1.scoreendl;/借助指针变量p输出它所指向的结构体变量各成员的值cout(*p).numt(*p).namet(*p).sext(*p).scoreendl;coutnumtnametsextscorenum。(2)结构体取成员的运算可以采用以下三种形式:结构体变量名.成员名(*结构体指针变量名).成员名结构体指针变量名-成员名2指向结构体指向结构体数组首元素的数组首元素的指针指针298返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举【例例2

229、-27】指向结构体的指针的使用。#includestructstudentintnum;charname20;charsex;intage;studentstu3=1,lilin,M,18,2,sum,M,19,3,zhao,M,20;voidmain()299返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举student*p;for(p=stu;pstu+3;p+)coutnumtnametsextageendl;程序的输出结果为:1lilinM182sumM193zhaoM20把stu赋给指针变量p,就表示p指向了该数组的首元素(p的值为数组的起始地址)。p+表示p指向数组的下

230、一个元素,利用这种方法可以访问数组中所有元素的值。/结构数组的应用例子结构数组的应用举例-排序.cpp300返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2.10.1.6 用结构体类型作为函数的参数用结构体类型作为函数的参数1用结构体类型的变量作函数的参数用结构体类型的变量作函数的参数(传值传值)在C+语言中,允许把结构体类型的变量直接作为函数的参数,但要注意:此时主调函数的调用点上的实参与被调函数相应位置上的形参必须是相同的结构体类型,是将实参的值(各成员的值)传递给相应的形参。【例例2-28】用结构体类型的变量作为函数的参数。#includeiostream.hstructs

231、tudentintnum;charname20;charsex;301返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举intage;voidprint(student);studentstu3=1,lilin,M,18,2,sum,M,19,3,zhao,M,20;voidmain()inti;for(i=0;i3;i+)print(stui);voidprint(students)couts.numts.namets.sexts.agetendl;302返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举程序的执行结果是:1lilinM182sumM193zhaoM20可

232、见,当把一个结构体类型的变量作为函数的参数时,可以将该变量的值(包含结构体类型中各成员的值)传递给被调函数的形参。2用指向结构体的指针作函数的参数(传指针)用指向结构体的指针作函数的参数(传指针)用指向结构体变量的指针作参数。这种方式同指针作为函数的参数的原理一致,传递的是结构体变量的地址(指针)。303返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举【例例2-29】用指针的方法实现例2-28程序的功能。#includeiostream.hstructstudentintnum;charname20;charsex;intage;voidprint(student*);Studen

233、tstu3=1,lilin,M,18,2,sum,M,19,3,zhao,M,20;304返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举voidmain()inti;for(i=0;i3;i+)print(&stui);voidprint(student*s)coutnumtnametsextagetendl;3用结构体变量的引用作为函数的参数用结构体变量的引用作为函数的参数此时,被调函数的形参必须声明成引用形式,函数的形参作为实参的一个别名来使用,从而达到对实参操作的目的。305返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举【例例2-30】用结构体变量引用的方法实

234、现例2-28程序的功能。#includeiostream.hstructstudentintnum;charname20;charsex;intage;voidprint(student&);studentstu3=1,lilin,M,18,2,sum,M,19,3,zhao,M,20;306返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举voidmain()inti;for(i=0;i3;i+)print(stui);voidprint(student&s)couts.numts.namets.sexts.agetendl;2.10.1.7 返回结构体类型的函数返回结构体类型的函

235、数1返回结构类型值的函数的定义返回结构类型值的函数的定义其定义格式如下:307返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举结构体名称函数名(形参及类型说明)函数体【例例2-31】定义一个返回结构体类型的函数,求所有同学中年龄最大的同学。#includeiostream.hstructstudentintnum;charname20;charsex;intage;studentmax(student*,int);308返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举studentstu3=1,lilin,M,18,2,sum,M,19,3,zhao,M,20;void

236、main()studentmaxold;maxold=max(stu,3);coutmaxold.numtmaxold.nametmaxold.ageage;index=0;for(i=0;in;i+)if(age1age)index=i;age1=(s+i)-age;return(*(s+index);309返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2返回结构的引用的函数返回结构的引用的函数与返回其它类型引用的函数的定义方法和原理一致,但注意不要返回一个局部变量的引用就可。2.10.1.8 结构的嵌套结构的嵌套C+语言中,允许定义一个结构体类型,该结构类型中可以包含另外一种

237、结构类型的成员。如下例中定义了一个birthday结构体类型,它含有year、month、day三个成员;又定义了第二个结构体类型student,它含有num、sex和birth三个成员,其中birth成员是birthday结构体类型。structbirthdayintyear;intmonth;intday;structstudentintnum;charsex;310返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举birthdaybirth;studentstu;/定义student结构体类型的变量stu此时要访问stu的birth成员的值时,要注意使用多个“.”操作符。如:s

238、tu.birth.year=1980;注意:C+语言中,不不能能定定义义一一个个结结构构体体类类型型,该该结结构构类类型型中中包包含含自自身身结结构构类类型型的的成成员员。但但可可包包含含指指向向自自身身结结构构类型的指针类型的指针。如:可定义:structstudentintnum;charname20;floatscore;student*next;不可定义:structstudentintnum;charname20;floatscore;studentnext;(例单链表的定义及运算例.cpp单链表的交集.C/单链表操作中指针作为函数参数的典型错误.cpp)311返回返回 2.10 结

239、构体、共用体和枚举结构体、共用体和枚举2.10.2 堆内存的分配和释放堆内存的分配和释放堆内存就是在程序的运行过程中根据需要而动态分配的一块内存,因此这种内存分配方式是动态分配,而不是静态分配(如:数组)。2.10.2.1 申请分配内存的方式申请分配内存的方式从内存中申请分配内存的方法有以下两种:(1)利用malloc函数格式是:void*malloc(字节数)该函数如分配内存成功,则返回其起始地址,否则返回NULL。当程序中使用malloc函数动态分配内存时,应该在程序的头部嵌入相应的头文件:#includeor#include312返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚

240、举如:int*p;p=(int*)malloc(sizeof(int);student*ps;ps=(student*)malloc(sizeof(student);(2)利用new运算符:格式1:指针变量名=new类型标识符;格式2:指针变量名=new类型标识符(初始值);格式3:指针变量名=new类型标识符内存单元个数;功能:如果分配内存成功,则返回其起始地址,否则返回0注意:格式1和格式2都是申请分配某一数据类型所占字节数的内存空间;但是在内存分配成功后,同时将一初值存放到该内存单元中;而格式3可同时分配若干个内存单元,相当于形成一个动态数组动态数组。313返回返回 2.10 结构体、共

241、用体和枚举结构体、共用体和枚举如:int*p,*q;student*r;p=newint;/申请分配1个int类型的内存空间(4个字节)p=newint(10);/申请1个int类型的内存空间,同时将该/内存单元中放置值10q=new int100; /申请分配100个int类型的内存空间(400B)r=newstudent;/申请分配1个student类型的内存空间/(sizeof(student)个字节)两种方法的区别:使用malloc函数分配内存时,其返回值要经经过过类类型型转转换换后才可赋给一个指针变量,而利用new分配内存时则不需要类型转换不需要类型转换。(例 aboutnew.cp

242、p) /sizeof面试题2.cpp sizeof面试题3.cpp314返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2.10.2.2 释放内存的方式释放内存的方式在C+语言中,当不再使用动态分配的内存空间时,可以将这部分内存释放,以方便其他程序代码使用。(1)利用free函数。格式:free(起始内存地址);使用时应嵌入相应的头文件:#include(2)利用delete运算符:格式1:delete指针变量名;格式2:delete指针变量名;说明:格式1可释放某一个内存单元;而格式2可释放若干个内存单元的空间。如:#include#include315返回返回 2.10 结构体

243、、共用体和枚举结构体、共用体和枚举voidmain(void)int*number,*p,*q;number=newint100;/申请分配100个int类型所占内存空间p=newint;/申请分配一个int类型所占内存空间(4个字节)q=(int*)malloc(10*sizeof(int);/申请分配10个int类型所占内存空间if(number=NULL|p=NULL|q=NULL)cout内存分配失败endl;elsecout内存分配成功endl;/程序的其它部分deletenumber;/释放number所指向的所有内存空间deletep;/释放p所指向的所有内存空间free(q);

244、/释放q所指向的所有内存空间(结构的应用实例:Josephus问题的结构(指针)解决P226动态一维数组和二维数组的C和C+实现.cpp结构数组及指针.cpp动态配置二维整型数组.cpp)316返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举使用动态存储分配时应注意: 一是要确认分配成功后才能使用,否则可能造成严重的后果; 二是在分配成功后不宜变动指针的值,否则在释放这片存储时会引起系统内存管理混乱; 三是动态分配的存储不会自动释放,只能通过delete释放。因此要注意适时释放动态分配的内存。/动态二维数组的产生与使用.cpp/动态三维数组的产生与使用.cpp317返回返回 2.1

245、0 结构体、共用体和枚举结构体、共用体和枚举2.10.3 共用体(联合体)类型共用体(联合体)类型1共用体概念共用体概念有时需要使几中不同类型的变量放到同一段内存单元中,如:把一个int型变量,char型变量,float型变量放于同一地址开始的内存单元中,这三个变量在内存中占的字节数不同,但都从同一地址开始存放,也就是使用覆盖技术,几个变量相互覆盖,这种使几个不同的变量共一段内存的结构称为共用体类型的结构也叫联合。2. 共用体类型的定义共用体类型的定义其定义格式为:union共用体名成员表变量表;318返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举如:unionDatainti;

246、charch;floatf;a,b,c;这表示定义了共用体类型Data,并同时定义了属于该种数据类型的变量a,b,c。由此可见:其定义方式与结构的定义方式类似,但二者的含义不同,结构体变量所占内存空间的大小,是各成员所占的内存之和,每个成员分别占有自己的内存单元,而共共用用体体变变量量所所占占的的内内存存空空间间大大小小于于等等于于占占用用内内存存空空间间最最大大的的成成员员的的长长度度,如上面定义的a,b,c三个共用体变量分别占4个字节。319返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举3共用体变量的定义共用体变量的定义(1)方法1:在定义共用体类型的同时定义该种类型的变量,

247、如上例中的变量a、b、c就是在定义unionData类型的同时定义的共用体变量。(2)方法2:可以用已定义过的共用体数据类型,定义共用体变量。格式是:union共用体名称变量名表;如:unionDatamydata;4共用体变量的引用共用体变量的引用共用体变量的使用方法基本同结构体变量的使用方法,并同时注意以下原则:(1)不不能能直直接接使使用用共共用用体体变变量量,而而只只能能使使用用共共用用体体变变量量的的成成员员,共用体变量取成员的运算符同结构体变量取成员的运算符,即用“.”。320返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举如:对于上例定义的共用体变量a来说,可用以下方

248、法引用其中的成员:a.i引用共用体变量a中的整型变量ia.ch引用共用体变量a中的字符变量cha.f引用共用体变量a中的浮点型变量f(2)共用体类型的特点:共用体类型可以使用覆覆盖盖技技术术使几个不同类型的变量(成员)共同占用和使用一块内存空间,所以,在在每每一一瞬瞬时时只只有有一一个个成成员员起起作作用用,其他的成员不起作用。如:a.i=1;a.c=a;a.f=2.1;之后,只有a.f是有效的,可以couta.f;但不能cout(b)?(a):(b)/宏定义面试题1.cpp宏定义面试题2.cpp宏定义面试题3.cpp2. 文件包含命令文件包含命令所谓“文件包含”是指将另一个源文件的内容合并到

249、当前程序中。C+中,文件包含命令的一般形式为:#include或#include”文件名”文件名一般是以.h为扩展名,因而称它为“头文件”,文件包含的两种格式区别在于:将文件名用“”括起来,用来包含那些由系统提供的并放在指定子目录中头330返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举文件;将文件名用双引号括起来的,用来包含用户自己定义的放在当前目录或其他目录下的头文件或其他源文件。文件包含可以将头文件中的内容直接引入,而不必再重复定义,减少了重复劳动,节省了编程时间。注意:一条#include命令只能包含一个文件,若想包含多个文件,则应使用多条包含命令。3. 条件编译命令条件编

250、译命令在一般情况下,源程序中的所有语句都会参加编译,但是有时候会希望根据一定的条件编译源文件的部分语句,这就是“条件编译”。条件编译使得同一源程序在不同的编译条件下得到不同的目标代码。在C+中,常用的条件编译命令有如下三种:331返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举(1)#ifdef标识符程序段1#else程序段2#endif该条件编译命令的功能是:如果在程序中定义了指定的“标识符”时,就用程序段1参与编译,否则,用程序段2参与编译。(2)#ifndef标识符程序段1#else程序段2#endif332返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举该条件编

251、译命令的功能是:如果在程序中未定义指定的“标识符”时,就用程序段1参与编译,否则,用程序段2参与编译。(3)#if常量表达式1程序段1#elif常量表达式2程序段2#elif常量表达式n程序段n#else程序段n+1#endif333返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举该条件编译命令的功能是:依次计算常量表达式的值,当表达式的值为真时,则用相应的程序段参与编译,如果全部表达式的值都为假,则用else后的程序段参与编译。2.10.7 文件及其操作文件及其操作文件是指存储在存储介质上的数据的集合。C+将文件看作是由一个一个字符(字节)的数据顺序组成的。它的组成形式可以分为:

252、ASCII文件和二进制文件。ASCII文件又称文本文件,它的每一个字节存放一个ASCII代码,代表一个字符;二进制文件是将数据用二进制形式存放在文件中,它保持了数据在内存中存放的原有格式。无论是文本文件还是二进制文件,都需要用“文件指针文件指针”来操纵。一个文件指针总是和一个文件相关联,当文件每一次打开时,文件指针指向文件的开始,随着对文件的操作,文件指针不断地在文件中移动,并一直指向最334返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举后处理的字符(字节)位置。对文件的操作有两种方式:顺序文件操作和随机文件操作。2.10.7.1 顺序文件操作顺序文件操作顺序文件操作,即从文件的

253、第一个字符(字节)开始,顺序地处理到文件的最后一个字符(字节),文件指针相应地从文件的开始位置到文件的结尾。顺序文件操作包括打开文件、读写文件和关闭文件三个步骤。文件的打开和关闭是通过使用fstream类的成员函数open和close来实现的。fstream类是用来对文件流进行操作,它和前面的标准输出输入流(cout、cin)一起,是C+实现流操作的最基本的类,而且它们有一个共同的基类ios。为了能使用这些类的相关函数,还必须在程序中添上相335返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举关的包含文件,例如:cout和cin的头文件是iostream.h,而fstream类的头

254、文件是fstream.h。ifstreamin;/objectofinputstreamofstreamin;/objectofoutputstreamfstreamin;/objectofinputandoutputstream1. 打开文件打开文件打开文件应使用成员函数open(),该成员函数的函数原型为:voidopen(constunsignedchar*filename,intnMode,intnPort=filebuf:openprot);其中:filename是一个字符型指针,指定要打开的文件名,文件名中可以包含驱动器号及多层子目录的完全路径名,在路径名中要用双反斜杠()将目录隔

255、开,通常可以用一对双引号包括的字符串常量作为实参,也可以用主函数main()的参数argv传递命令行。如:ifstreamf1;f1.open(“e:userfilename.cpp”);/缺省时把nMode设置为ios:in/输入文件流f1与文件filename.cpp相关联,即打开一个文本文件进行读操作336返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举在使用f1之前,必须先建立一个文件缓冲器,并将这个流对象和文件缓冲器以及一个真实的物理文件连接起来。这两项任务由ifstream中的成员函数open()完成。如果打开一个文件,一切正常,则为该磁盘文件建立了一个输入缓冲器,且g

256、et指针指向缓冲器的起始位置。mode指定文件的打开方式,其值如表2.13所示;nPort表示文件保护方式,与操作系统有关,用户一般只使用缺省值,即不写该参数。(指定了文件的系统属性,其取值为:0一般文件2隐藏文件1只读文件3系统文件表2.13在ios类中定义的文件打开方式)337返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举文件打开方式含义ios:in以输入(读)方式打开文件ios:out以输出(写)方式打开文件ios:app打开一个文件使新的内容始终添加在文件的末尾ios:ate文件打开时,文件指针位于文件尾ios:trunc若文件存在,则清除文件所有内容;否则,创建新文件i

257、os:binary以二进制方式打开文件,缺省时以文本方式打开文件ios:nocreat打开一个已有文件,若该文件不存在,则打开失败ios:noreplace若打开的文件已经存在,则打开失败ios:in|ios:out以读/写方式打开文件ios:in|ios:binary以二进制读方式打开文件ios:out|ios:binary以二进制写方式打开文件表2.13在ios类中定义的文件打开方式338返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举例:以提取文本数据的方式打开一个文件,其方法如下:ifstreaminfile1(“file1.txt”,ios:in);/ios:in可缺省o

258、fstreamf2;f2.open(“file2.cpp”,ios:out);/ios:out可缺省fstreamf;f.open(“file.cpp”,ios:in|ios:out);/缺省打开方式时以文本方式打开。在这种情况下,输入时回车/换行符要转换为字符n,在输出时,字符n转换为回车/换行符,这些转换在二进制方式下是没有的。这是文本方式与二进制方式的主要区别。此句与下面两句等价:ifstreaminfile1;/创建infile1输入流infile1.open(“file1.txt”,ios:in);/将 输 入 流 与 文 件 “file1.txt”关 /联,即打开文件以提取二进制数

259、据的方式打开一个文件的方法如下:ifstreaminfile2(“file2.txt”,ios:in|ios:binary);或写成:ifstreaminfile2;infile2.open(“file2.txt”,ios:in|ios:binary);339返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举流操作过程可能会出错,例如打开一个不存在的文件进行操作,或读一个不允许读(或写)的文件,或用不正确格式写入数据等都将产生错误,必须进行检测并加以处理,检测流错误的办法很多,通常采用:if(!f1)if(f1)340返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2.

260、关闭文件关闭文件在文件操作结束时,应及时调用成员函数close()来关闭文件。如要关闭的文件(指针)为myfile,则可使用如下语句关闭文件:myfile.close();3. 文件的读写文件的读写在打开文件后,就可以对文件进行读写操作了。文本文件的读写可以直接使用插入符“”,也可以使用get()/put()函数或read()/write()函数;二进制文件的读写则只能使用get()/put()函数或read()/write()函数。二进制文件的处理过程与文本文件的处理过程基本相同,但在判断文件是否结束时有所区别。在文本文件中,遇到文件结束符时,get()函数返回一个文件结束标志EOF,该标志

261、的值为-1。但在处理二进制文件时,读入某一个字节中的二进制的值可能是-1,与EOF的值相同。为了避免将读入的有用数据处理成“文件结束”,C+提供了一个成员函数eof()判断文件是否结束。当达到文件尾时,它返回一个非零值,否则返回零。341返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举当文件不指明打开方式时,即缺省时,则以文本方式打开。在这种情况下,输入时回车/换行符要转换为字符“n”,在输出时,字符“n”转换为回车/换行符,这些转换在二进制方式下是没有的。这是文本文件和二进制文件的主要区别。(1)文本文件的读/写文本文件的读操作通常采用istream类中的成员函数get(),写成

262、:ifstreamf1(“file1.cpp”);while(f1)charc;f1.get(c);coutc;由于ifstream类由istream类派生而来,它会自动地调用成员函数:istream&get(char&c);342返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举每次读取f1中的单个字符传给c,然后传递给CRT显示器,文件在get指针的控制下按顺序读取,知道EOF,编程者可不必关心具体实现细节。如果不是写到标准流对象cout,而是写到另一个文件中,则在进行写操作前,必须打开另一个文件,写成:Ofstreamf2(“file2.cpp”);if(!f2)cerr“aC

263、antopenfile2.cpp.n”;exit(1);charc;while(f2&f1.get(c)f2.put(c);343返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举在while循环语句中,程序每次从f1中读取一个字符,然后由put()写到f2中,实际上是从与f1相关联的输入缓冲器中读取一个字符,写到与f2相关联的输出缓冲器中,由于get指针和put指针能自动增1,故确保了字符的读写顺序。当get指针指到输入缓冲器的终止位置时,说明整个文件已读完,此时输出缓冲器已复制了整个文件的内容,f1.get(c)读到文件尾则测试得该表达式为假(false),则程序跳出循环,执行后

264、续语句。顺便指出,与文本文件相关联的缓冲器以NULL结尾。如前所述,对于文本文件经常采用读取一行字符串的重要函数 getline(),写成:ifstreamf1(“file1.cpp”);if(!f1)cerr“aCantopenfile2.cpp.n”;exit(1);While(f1)charbuf100;f1.getline(buf,sizeof(buf);coutbuf;344返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举(2)二进制文件的读写二进制文件不含空白符,数据没有通过换行符组织成一行行的形式,任何8位(bit)值都可能出现。因此,将二进制文件调到屏幕上显示出的信

265、息很难看懂。通常是利用ostream类的成员函数write()将数据写到二进制文件。写二进制数据有两种方法:一是一次写入一个字符,使用成员函数put(charc);二是一次写一组字符(但不是以终止符结束),则使用ostream&write(constchar*pch,intnCount);为了便于调试,一般采用按字符形式格式化的方法,通过强制类型转换,将程序中要写入文件的对象或对象数组转换成字符串形式,写入二进制文件,其调用语句的一般格式为:输出文件流对象名.write(char*)&对象名或&对象数组名下标,sizeof();同样读二进制文件的方法通常是将文件按字符形式格式化的方法读入到一个

266、与写入时同类的对象或对象数组中,其调用语句的一般格式为:输入文件流对象名.read(char*)&对象名或&对象数组名下标,sizeof();345返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举这样一来,可对二进制文件读写任何类型的数据。/例二进制文件的读写.cpp如前所述,read()与write()的原型为:istream&read(char*pch,intnCount);ostream&write(constchar*pch,intnCount);例中是读写结构体Person的结构数组people。read()成员函数从输入流中读取nCount个字节,并把它们存放在pch所

267、指的缓冲器中。write()成员函数是将nCount个字节从pch所指的缓冲器取出,写到输出流。本程序中write()是对结构数组people2进行操作,由于它不是字符型数组,故必须进行强制类型转换。结构数组people1的数据结构如图所示,结构数组 people2的数据结构与peopl1一样,因此写到d:testPersonal.dat文件中共有26个字节的二进制数据。346返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举W ang01.6525Zhang0 1.7224Zhang0 1.7224Zhang0 1.7224people0people1people2people33

268、47返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举此例中写数据是否结束由cnt变量控制,不能只靠f1表达式,它只能检测写操作是否出错而不能判终,若取消cnt4,表达式将变成无穷循环。如前所述,以二进制方式打开的文件,其关联的缓冲器不是以NULL结尾。/例带命令行参数的文件.cpp348返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举【例例2-32】向文本文件中分别写入一个整数、一个浮点数和一个字符串。#include#include#includevoidmain(void)fstreammyfile;myfile.open(f1.txt,ios:out); /以写方

269、式打开文件f1.txtif(!myfile)coutCantopenfile!endl;abort(); /退出程序,包含在stdlib.h中myfile20endl;myfile4.58endl;myfileHelloWorld!endl;myfile.close();349返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举例从文本文件中读取数据例程#include#include/有关文件输入、输出的定义文件#includevoidmain(void)chara101;ifstreaminfile3;infile3.open(“filein3.txt”,ios:in);/读取in

270、file3输入流的数据if(!infile3)cout“Itcannotopenthefile!”endl;abort();while(!infile3.eof()infile3.getline(a,sizeof(a);coutaendl;infile3.close();350返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举例文本文件复制例程/file文件复制操作.cpp#include#include/有关文件输入、输出的定义文件#includevoidmain(void)charch;fstreaminf,outf;inf.open(d:filein.txt,ios:in);i

271、f(!inf) coutItcannotopenthefile!endl;abort();outf.open(d:fileout.txt,ios:out);if(!outf)coutItcannotopenthefile!endl;abort();while(!inf.eof()&inf.get(ch)/按字符读取文件filein.dat的数据outf.put(ch);/将数据按字符写入文件fileout.dat中inf.close();outf.close();(例:文件操作例.cpp)351返回返回 2.10 结构体、共用体和枚举结构体、共用体和枚举2.10.7.2 随机文件操作随机文件操

272、作随机文件操作,即在文件中通过C+相关的函数移动文件指针,并指向所要处理的字符(字节)。随机文件提供在文件中来回移动文件指针和非顺序地读写文件的能力,这样在读写文件中的某一数据之前不需要再读写其前面的数据,从而能快速地检索、修改和删除文件中的信息。在istream类中提供了3个操作读指针的成员函数:istream&istream:seekg(longpos);istream&istream:seekg(longoff,dir);streamposistream:tellg();其中:pos为文件指针的绝对位置;off为文件指针的相对偏移量;dir为文件指针的参照位置,其可能值为:352返回返回

273、 2.10 结构体、共用体和枚举结构体、共用体和枚举iso:cur=1文件指针的当前位置iso:beg=0文件开头iso:end=2文件尾tellg()函数没有参数,它返回一个long型值,用来表示从文件开始处到当前指针位置之间的字节数。在ostream类中同样提供了3个操作写指针的成员函数:ostream&istream:seekp(longpos);ostream&istream:seekp(longoff,dir);streamposistream:tellp();这3个成员函数的含义与前面3个操作读指针的成员函数相同,只不过它们是用来操作写指针的。(例:随机文件操作例.cpp)353返

274、回返回 本章小结本章小结本章是C+语言的基础,内容与C语言多数一致。C+语言支持面向对象的程序设计(OOP),在面向对象的程序设计中,以“对象”为中心,并且将对象的属性和方法二者封装在一起,这种结合自然地反映了应用领域的模块性,因此具有相对稳定性。同时OOP又引入了“类”(class)的概念。类与类以层次结构组织,属于某个类的对象除具有该类所描述的特性外,还继承了层次结构中该类上层所有类描述的全部性质,OOP方法的模块性与继承性,保证了新的应用程序设计可在原有对象的数据类型和功能的基础上,通过重用、扩展和细化来进行,而不必从头做起或复制原有代码,这样,大大减少了重新编写新代码的工作量,同时降低

275、了程序设计过程中出错的可能性,达到了事半功倍的效果。354返回返回 本章小结本章小结一个C+的程序是由函数构成的,程序中有且仅有一个main函数,它总是从主函数main开始运行。每个C+的源程序要以.CPP作为程序存盘时的文件名后缀,源程序需要经过C+编译系统的编译和连接,最后才能产生可运行的.EXE程序文件。C+源程序数据的输入和输出通常利用输入/输出流对象cin和cout来完成,这时要求在程序的开头需要嵌入头文件iostream.h。程序的核心任务是对数据进行加工和处理,在C+中任何数据是有类型的,不同的数据类型的关键字不同,所占存储单元的大小不同,因而表示数的范围大小也不同。另外,根据数

276、据在程序运行过程中是否发生变化将数据分为常量和变量,常量的值固定不变且数据类型是由用户在程序中的书写格式来决定,而变量则必须在程355返回返回 本章小结本章小结中进行明确的定义,即定义其名称和类型,在程序中,任何变量都要遵循先定义后使用的规则。C+为每种运算符规定了一个运算的优先级和结合特性,以控制各种运算的顺序,利用圆括号可以改变表达式的运算顺序。当在表达式中进行运算的数据类型不同时,C+将自动进行隐式转换,当然,用户也可利用强制类型转换的方法进行转换。利用程序的三种结构即:顺序结构、选择结构和循环结构可以实现对程序执行流程的控制。选择结构可使程序根据某个(些)条件是否成立,从而有选择的执行

277、程序中的程序段,这可以利用if语句实现。而循环结构可使某一段程序有条件地重复执行有限次,可利用while、do-while和for语句实现,并且这些语句可以通过改变条件的形式进行相互转化。356返回返回 本章小结本章小结数组是一个由若干相同类型的变量组成的集合,数组中特定的元素通过下标来访问,同一个数组中所有元素所占存储单元是连续的,整个数组所占存储单元的首地址就是数组中的第一个元素的地址,数组名本身代表了数组的首地址。当数组用于存放字符串时,由于字符串具有结束标记0,所以在定义字符数组的大小时,要多定义一个元素。指针就是某一存储单元的地址,指针变量是专门存放其他变量指针的变量,当指针变量中存

278、放了某一变量的地址时,则称该变量指向那个变量。因此,指针变量可以指向变量、数组、函数、字符串、结构体等。指针还可以作为函数的参数,以传递实参的地址。当程序代码量较大时,可根据功能的不同分成更小、更容易管理的模块,这种模块就是函数。程序中所用的357返回返回 本章小结本章小结函数有两类,一类是库函数,另一类是用户自定义函数,库函数可直接使用,而用户自定义函数要先定义后使用。一个函数可定义成有参函数,也可定义成无参函数,当函数无返回值时,要把函数的类型定义成void。定义函数时,函数名称后面括号内的参数是形式参数,形式参数可以是普通变量、数组名、指针变量、引用等。当发生函数调用时,实参与形参间发生

279、了数据传递,要注意传值与传地址间的区别。内联函数是为了提高编程的效率而实现的,它适用于函数体代码较少且程序中不含有复杂程序结构的情况。函数重载允许用同一个函数名定义多个函数,系统会根据传递给函数的参数的数目、类型和顺序调用相匹配的函数,函数重载使程序设计简单化。在函数定义中通过赋值运算可指定参数的默认值。358返回返回 本章小结本章小结引用是C+语言独有的特性,引用就是某一变量的别名,在定义时必须初始化,使用引用的主要目的是在函数参数传递过程中解决大对象的传递效率和空间不如意的问题。当利用引用作为函数的参数时,参数的传递过程中不产生值的副本。不允许声明引用数组,但可以用常量来初始化引用声明。当

280、一个函数返回引用时,要注意局部对象返回的危险。结构体是一种将不同数据类型的成员组织到一起的构造数据类型,因此,当定义结构体时,不产生内存的分配,只有在定义了结构体的变量时,才分配内存单元。当结构体作为函数的参数进行传递时,其值进行了复制,因此,当结构体很大时,宜采用结构体的引用传递函数参数。在使用结构体变量时,不能直接把它当成一个整体去使用,359返回返回 本章小结本章小结而只能访问和使用结构体中的成员。结构体取成员的方法是“结构体变量名.成员名”。另外,在程序中可以定义结构体数组,也可以定义指向结构体的指针。利用new运算符可以进行动态地分配内存,利用delete运算符可以释放已分配的内存。C+允许使用关键字typedef为已有的数据类型定义新的名称,称为类型定义。类型定义只是为已有的数据类型生成一个别名,并不是定义了新的数据类型。数据文件的打开和关闭是通过使用fstream类的成员函数open和close来实现的。fstream类是用来对文件流进行操作,它和标准输出输入流(cout、cin)一起,是C+实现流操作的最基本的类,而且它们有一个共同的基类ios。为了能使用这些类的相关函数,还必须在程序中添上相关的包含文件iostream.h和fstream.h。360

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

最新文档


当前位置:首页 > 高等教育 > 研究生课件

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