武汉大学C++完整讲义(李春葆)_第1页
武汉大学C++完整讲义(李春葆)_第2页
武汉大学C++完整讲义(李春葆)_第3页
武汉大学C++完整讲义(李春葆)_第4页
武汉大学C++完整讲义(李春葆)_第5页
已阅读5页,还剩689页未读 继续免费阅读

下载本文档

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

文档简介

课程:面向对象的程序设计目前支持面向对象程序设计的主要环境:

•C++•Java教材

C++程序设计,清华大学出版社,刘加海等,2009年C++程序设计,清华大学出版社,李春葆等,2005年上机环境:VisualC++6.0第1章C++概述1.1C++的发展历史

C++源于C语言。1972年至1973年期间,D.M.Ritchie首创了一种新的程序设计语言,取名为C语言。设计C语言的最初目的是编写操作系统。由于其简单、灵活的特点,C语言很快就被用于编写各种不同类型的程序,从而成为世界上最流行的语言之一。C语言是面向过程的语言->C++是面向对象的语言,称为“带类的C”,1993年正式取名为C++。C++改进了C的不足之处,支持面向对象的程序设计,在改进的同时保持了C的简洁性和高效性。

C++编译系统:Microsoft公司的VisualC++6.0、Borland公司的BorlandC++5.02等。1.2程序设计语言和程序设计方法1.2.1程序和程序设计语言计算机程序是对计算机处理对象和计算规则的描述。程序设计语言是用来描述计算机事务处理过程、便于计算机执行的规范化语言。无论自然语言还是计算机语言,其基础是一组记号和规则,根据规则由记号构成记号串的总体就是语言。我们知道,人类自然语言(如汉语)是人们交流和表达思想的工具。那么,人与计算机如何“交流”呢?为此,就产生了计算机语言,其功能是人用计算机语言编写一系列的动作,计算机能够“理解”这些动作,按照指定的动作去执行。正是这种相同点,所以计算机语言和自然语言都叫作“语言”。

自然语言由于其历史性和文化性,除了其语法外,还包含复杂的语义和语境,所以,人们也能理解很多不完全符合语法的语句。但计算机语言是人发明的,它主要是用语法来表达人的思想,因而在编写程序时要严格遵守语法规则。如同人类有很多自然语言一样,计算机语言也有很多种。按照计算机历史的发展有如下几类:

机器语言它是面向机器的,是特定计算机系统所固有的语言。用机器语言进行程序设计,需要对机器结构有较多的了解。用机器语言编写的程序可读性很差,程序难以修改和维护。

汇编语言为了提高程序设计效率,人们考虑用有助记忆的符号来表示机器指令中操作码和运算数,例如用ADD表示加法,SUB表示减法等。相对机器语言来看,用汇编语言编写程序的难度有所降低,程序的可读性,有所提高,但仍与人类的思维相差甚远。高级语言汇编语言和计算机的机器语言十分接近,它的书写格式在很大程度上取决于特定计算机的机器指令,这对于人们抽象思维和交流十分不便。高级语言指的是像Fortran、C、Pascal和Basic等与具体机器无关的语言,这样程序设计者不需要了解机器的内部结构,只要按照计算机语言的语法编写程序即可。1.2.2结构化程序设计出现高级语言之后,如何用它来编写较大的程序呢?人们把程序看成是处理数据的一系列过程。过程或函数定义为一个接一个顺序执行的一组指令。数据与程序分开存储,程序设计的主要技巧在于追踪哪些函数和调用哪些函数,哪些数据发生了变化。为解决其中可能存在的问题,结构化程序设计应运而生。C程序由函数组成,从组织形式上看,函数亦称为模块,每个模块实现一个单一的功能,这称为模块化程序设计。模块化程序设计的思想是,按照自顶向下的原则,把问题逐层分解。先从总体出发,把问题分成若干个大块,每一大块代表一个大任务;在此基础上再对每个大块细化,把大任务变成若干个小任务。这一过程叫做逐步求精,直到每个小任务都能用基本结构(顺序、分支和循环3种结构之一)表示为止。在划分模块的过程中,应保证模块的单入口单出口、完整性和独立性,这种方法称为结构化程序设计。

结构化程序设计仍然存在诸多问题:

生产率低下软件代码重用程度低软件仍然很难维护针对结构化程序设计的缺点,人们提出了面向对象的程序设计方法。1.2.3面向对象的程序设计面向对象程序设计的本质是把数据和处理数据的过程当成一个整体即对象。一般认为,面向对象程序语言至少包含下面一些概念:

对象对象是人们要进行研究的任何实际存在的事物,它具有状态(用数据来描述)和操作(用来改变对象的状态)。面向对象语言把状态和操作封装于对象体之中,并提供一种访问机制,使对象的“私有数据”仅能由这个对象的操作来执行。用户只能通过向允许公开的操作提出要求(消息),才能查询和修改对象的状态。这样,对象状态的具体表示和操作的具体实现都是隐蔽的。

类把众多事物归纳、划分成一些类,把具有共性的事物划分为一类,得出一个抽象的概念,是人类认识世界经常采用的思维方法。类是面向对象语言必需提供的用户定义的数据类型,它将具有相同状态、操作和访问机制的多个对象抽象成为一个对象类。在定义了类以后,属于这种类的一个对象叫作类实例或类对象。一个类的定义应包括类名、类的说明和类的实现。

继承继承是面向对象语言的另一个必备要素。类与类之间可以组成继承层次,一个类的定义(称为子类)可以定义在另一个已定义类(称为父类)的基础上。子类可以继承父类中的属性和操作,也可以定义自已的属性和操作,从而使内部表示上有差异的对象可以共享与它们结构有共同部分的有关操作,达到代码重用的目的。面向对象程序设计的主要优点是:

与人类习惯的思维方式一致结构化程序设计是面向过程的,以算法为核心,把数据和过程作为相互独立的部分。面向对象程序设计以对象为中心,对象是一个统一体,它是由描述内部状态表示静态属性的数据以及可以对这些数据施加的操作封装在一起所构成的。面向对象设计方法是对问题领域进行自然分解,确定需要使用的对象和类,建立适当的类等级,在对象之间传递消息实现必要的联系,从而按照人们习惯的思维方式建立起问题域的模型,模拟客观世界。

可重用性好面向对象的软件技术在利用可重用的软件成分构造新的软件系统时有很大的灵活性。有两种方法可以重复使用一个对象类:一种方法是创建该类的实例,从而直接使用它;另一种方法是从它派生出一个满足当前需要的新类。继承性机制使得子类不仅可以重用其父类的数据结构和程序代码,而且可以在父类代码的基础上方便地修改和扩充,这种修改并不影响对原有类的使用。人们可以像使用集成电路(IC)构造计算机硬件那样,比较方便地重用对象类来构造软件系统。

可维护性好类是理想的模块机制,它的独立性好,修改一个类通常很少会牵扯到其他类。如果仅修改一个类的内部实现部分(私有数据成员或成员函数的算法),而不修改该类的对外接口,则可以完全不影响软件的其他部分。面向对象软件技术特有的继承机制,使得对软件的修改和扩充比较容易实现,通常只要从已有类派生出一些新类,无须修改软件原有成分。面向对象软件技术的多态性机制,使得扩充软件功能时对原有代码所需作的修改进一步减少,需要增加的新代码也比较少。所以,面向对象方法设计的程序具有很好的可维护性。1.3C++语言的特点

C++语言的主要特点在于它支持面向对象程序设计。下面说明它和面向对象有关的一些特征。

1.类和数据封装

2.构造函数和析构函数

3.访问限制符和信息隐蔽性

4.对象和消息

5.友元

6.运算符重载和函数重载

7.继承和派生类

8.虚函数1.4C++程序开发过程

C++程序开发过程与其他高级语言源程序开发过程的原理是一样的,一般,都要经过编辑、编译和执行三个步骤。

编辑源程序:生成文本文件(file.cpp)

编译:生成一个目标文件(file.obj)

连接:生成一个可执行文件(file.exe)1.5C++程序结构1.5.1简单的C++程序我们用一个简单的程序例子来分析C++的程序构成。以下代码是一个完整的可以执行的C++程序:/*-----------------------------------------

文件名:ch1.cpp------------------------------------------*/#include<iostream.h>#include<math.h>voidmain(){ inti,j,k; //说明变量

i=2;j=8; //变量赋值

k=pow(i,j); cout<<i<<"的"<<j<<"次方="<<k<<endl;}1.5.2C++程序的组成一个C++程序由以下基本部分组成:

1.预处理命令

2.输入和输出

3.函数

4.语句语句是组成程序的基本单元。函数是由若干条语句组成的。但是,空函数是没有语句的。语句由单词组成,单词间用空格符分隔,C++程序中的语句又是以分号结束。一条语句结束时要用分号,没有结束时不要用分号。

在C++语句中,表达式语句最多。表达式语句由一个表达式后面加上分号组成。任何一个表达式加上分号都可以组成一条语句。只有分号而没有表达式的语句为空语句。语句除了有表达式语句和空语句之外,还有复合语句、分支语句、循环语句和转向语句等若干类。

5.变量多数程序都需要说明和使用变量。变量的类型很多,这充分体现了C++数据类型丰富的特点。1.5.3C++语言的风格C++语言的风格概括如下:

C++语言严格区分大小写英文字母。

C++语言用“;”作为语句分隔符。

C++语言中大括号“{”和“}”用于标识一个语句组,即构成一个复合语句,因此必须配对使用。

C++程序书写格式自由,一行内可以写几个语句,一个语句可以写在几行上。可以使用//或/*...*/对C++程序中的任何部分作注释。一行一般写一条语句。短语句可以一行写多个。长语句可以一条写多行。第2章C++数据类型程序用于处理数据,而数据是以变量或常量的形式存储,每个变量或常量都有数据类型。数据类型是最基本的元素。确定了数据类型,才能确定变量的空间大小和其上的操作。

C++提供了丰富的数据类型,归纳起来,分为基本数据类型和复合数据类型。数据类型与操作是不可分割的,而操作是通过运算符实现的,例如:

intb=3,c=4;

a=b+c;//a、b和c是整型变量,进行加法操作2.1基本数据类型基本数据类型有5种:

•整型(int)

•单精度浮点型(float)

•字符型(char)

双精度浮点型(double)

•无值型(void)

名称字节数int4shortint2longint4unsignedint4unsignedshortint2unsignedlongint4char1unsignedchar1float4double8longdouble10表2.1系统数据类型的数据占用的字节数

2.2常量和变量2.2.1常量常量是在程序中不能改变的量。C++支持4种类型的常量:浮点型、整型、字符型和枚举型。

1.整型常量整型数据表示通常意义上的整数,如34,-4,0,1234。整型量在C++中用int定义。整型常量可以用十进制、八进制或十六进制表示,例如整数20可以表示为:

20 //十进制

024 //八进制数以0开头

0x14 //十六进制数以0x开头

整型常量可以后跟字母l或L表示long型(长整数),也可以跟u或U表示unsigned整数(无符号整数),如以下数是合法的:

135u //无符号整数

8846UL //无符号长整数

5L //长整数

10lu //无符号长整数2.浮点数常量

浮点数也和数学意义的浮点数类似。浮点数分为整数部分和小数部分。一个浮点数常量可以用科学记数法和通常的十进制数表示法表示。科学记数法格式:

[d][.d][[E|e][+|-]d]

其中,d是一位或多位十进制数字(0~9)。E(也可用e)是指数符号。小数点之前的是整数部分,小数点之后是尾数部分,它们是可省略的。小数点在没有尾数时可省略。浮点常量可用字母F或f标志。如以下数是合法的:

3.14159F0.121.0E-32.f

以下数是不合法的:

E+2.51.25F-23.字符常量与字符串常量

C++中的字符常量常用单引号括起,如‘3’、‘b’和‘’分别表示字符3、字符b和空白字符。在内存中,字符数据以ASCII码存储,如字符'a'的ASCII码为97,字符'*'的ASCII码为42。有些字符是可以显示的,如字母、数字和一些符号'!'、'@'、'#'、'+'、'/'等,而有些字符不可显示,如ASCII码为8的字符表示退格(backspace),ASCII码为13的字符表示回车等。

当0个或多个字符由双引号"…"括起时,就组成字符串常量。以下是字符串常量的例子:

"" //空串

"abcd" //一般字符串

"a\n\rb" //带特殊符号的字符串

字符串常量实际上是一个字符数组,组成数组的字符除显式给出的外,还包括字符结尾处标识字符串结束的符号‘\0’,所以字符串“abc”实际上包含4个字符:‘a’、‘b’、'c'和'\0'。2.2.2变量变量就是值可变的量。每个变量由一个变量名惟一标识,同时,每个变量又具有一个特定的数据类型。类型标志着这个变量将来的用法以及它将保存哪种类型的数据值。

1.命名变量名变量名要遵守以下规则:(1)不能是C++保留字。C++的保留字如表2.3所列。(2)第一个字符必须是字母或下划线。中间不能有空格。(3)变量名中除了使用26个英文大小写字母和数字外,只能使用下划线。(4)一般不要超过31个字符。(5)变量名不要与C++中的库函数名、类名和对象名相同。例如,以下都是有效的变量名:

i1,count,_fnum,str_1

以下不是有效的变量名:

1abc,a-b,abc【例】下列变量名中合法的是

A.B.C.Tom B.3a6bC._6a7b D.$ABC

答:选项A中出现“.”字符错误;选项B中以数字开头错误;选项D中出现“$”字符错误;本题答案为:C。2.变量定义和说明

C++中,变量使用之前一定要定义或说明,变量定义的格式一般为:

[修饰符]类型变量名;//注释其中,类型指出变量所存放的数据的类型;变量名是任意合法的变量名;注释指明该变量的含义和用途;修饰符进一步描述了变量的使用方式。修饰符和注释是任选的,可以没有。“说明”和“定义”之间是有区别的,两者的语法格式类似。“说明”是向计算机介绍名字,它说“这个名字是什么意思”。而“定义”则为这个名字分配存储空间。无论涉及到变量时还是函数时含义都一样。无论在哪种情况下,编译器都在“定义”处分配存储空间。对于变量,编译器确定这个变量占多少存储单元,并在内存中产生存放它们的空间。对于函数,编译器产生代码,并为之分配存储空间。3.变量初始化在定义变量时可以给变量赋一个初值,初值可以是一个表达式,但该表达式必须在编译时就能计算出值来。系统自动计算得到一个值后,赋给该变量。下面是一些变量初始化的例子:

constdoublePI=3.14159;inti=10;floata=1.4;b=a*5;2.3运算符和表达式在程序中,表达式是计算求值的基本单位,它是由运算符和运算数组成的式子。运算符是表示进行某种运算的符号,C++规定了很多有特定功能的运算符,如“+”表示加减运算。运算数包含常量、变量和函数等。运算符与运算数有关,如:

5.0/2=2.55/2=2 //整除

2.3.1算术运算符

C++定义了5种简单的操作,即加(+)、减(-)、乘(*)、除(/)和取模(%),其中乘(*)、除(/)和取模(%)优先于加(+)减(-)。括号用来表示一组项的计算,计算时,先计算括号内表达式的值,再将计算结果与括号外的数一起计算,如:

4*(1+2)=4*3=12//先计算1+2的结果取模运算符(%)用于计算两整数相除后得到的余数,如:

22%7//结果为1

注意:%只能用于整数相除,不能对浮点数操作。2.3.2赋值运算符赋值运算符“=”将其右侧的表达式求出结果,赋给其左侧的变量。例如:

inti;i=4*(1+2);//i的值变为12

赋值表达式本身的运算结果是右侧表达式的值,而结果类型是左侧变量的数据类型。例如:

inti=2.8*4;//结果为11,而不是11.2

赋值运算符的结合性是从右至左的,因此,C++程序中可以出现连续赋值的情况。另外,还有一类复合运算符:a+=b 等价于 a=a+ba-=b 等价于 a=a-ba*=b 等价于 a=a*ba/=b 等价于 a=a/ba%=b 等价于 a=a%ba<<=b 等价于 a=a<<ba>>=b 等价于 a=a>>ba&=b 等价于 a=a&ba^=b 等价于 a=a^ba|=b 等价于 a=a|b

使用赋值运算符需要注意的是,运算符左边必须是一个左值(lvalue),即它必须代表一个有效的内存地址,必须能给它赋值。常量不能作为左值,一般的表达式如a+b*c也不能作为左值,因为它只代表一个值,不代表一个内存地址。例如,以下语句错误:

a+b=a;【例】若变量a是int类型,并执行了语句:a='A'+1.6;,则正确的叙述是

A.a的值是字符C B.a的值是浮点型

C.不允许字符型和浮点型相加

D.a的值是字符'A'的ASCII值加上1。答:a='A'+1.6中1.6转换为int数即1。本题答案为:D。【例】以下程序的输出结果是

#include<stdio.h>main(){inta=3;printf("%d\n",(a+a-=a*a));}A.–6 B.12C.出错 D.-12

答:a+a-=a*a计算错误,该表达式中,*运算符优先级最高,先执行a*a返回9,+运算符次之,执行a+a得到6,再执行6-=9,赋值运算符右边是常量,出现错误。本题答案为:C。2.3.3等值、关系和逻辑运算符等值、关系和逻辑运算符的运算结果为true(真)或false(假),分别用值非0(true)或0(false)表示。C++中的关系和逻辑运算符如下:

!(逻辑反),<(小于),

<=(小于等于),>(大于),

>=(大于等于),==(等于),

!=(不等于),&&(逻辑与),

||(逻辑或)【例】设intx=1,y=2;表达式(!x||y--)的值是

A.0 B.1C.2 D.-1

答:先计算!x返回0,再计算y--返回1,两者进行逻辑或运算,返回1。本题答案为:B。【例】已有定义:intx=3,y=4,z=5,则表达式!(x+y)+z-1&&y+z/2的值是

A.6 B.0C.2 D.1

答:(x+y)返回7,!(x+y)返回0,!(x+y)+z-1=4即为逻辑真(1),y+z/2=6即为逻辑真(1),两者执行逻辑与运算返回1。本题答案为:D。2.3.4自增、自减运算符自增(++)、自减(--)运算符为变量的增1和减1提供了紧凑格式:

a++ 等价于a=a+1a-- 等价于a=a-1

需要说明的是,自增、自减符号既可位于变量的前面,也可位于变量的后面。在单独作为一个表达式时,++a和a++效果一样,都是将变量a自增1。若作为一个复杂表达式的一部分,前缀++表示先将其后面的变量值增1,然后将增1后的变量参与表达式运算,而后缀++表示将其前面的变量先参与表达式运算,然后变量本身增1。例如,若a=1,b=2,则(a++)+b的结果为3,而(++a)+b的结果为4。自减运算符含义类似。【例】C语言中,关于自增和自减运算符使用正确的是

A.10++ B.(x+y)--C.d+++d+++d++ D.++(a-b)

答:++不能作用于常量和表达式。本题答案为:C。【例】已知:inti=6,j;则语句j=(++i)+(i++)后的j值是

A.4 B.14C.13 D.15

答:先执行++i返回7(i=7),再执行i++返回7(i=8),所以j=7+7=14。本题答案为:B。2.3.5条件运算符条件运算符是C++中惟一具有3个操作数的运算符,其格式如下:表达式1?表达式2:表达式3

它的运算方式为:先计算表达式1的值,如果其值为非零(真),则表达式2的值就是整个表达式的最终结果;否则表达式3的值就是整个表达式的值。【例】若w=1,x=2,y=3,z=4,则条件表达式w>x?w:y<z?y:z的结果是

A.4 B.3C.2 D.1

答:由于w>x为假,返回表达式y<z?y:z,又由于y<z为真,返回y的值即3。本题答案为:B。【例】若给定条件表达式(M)?(a++):(a--),则其中表达式(M)

A.和(M==0)等价 B.和(M==1)等价

C.和(M!=0)等价 D.和(M!=1)等价答:(M)条件表达式的结果是一个逻辑值,表示M是否为真,它与M!=0等价,因为M为真时,M!=0亦为真,M为假时,M!=0亦为假。所以本题答案为C。2.3.6位运算符位(bit)是计算机中表示信息的最小单位,一般用0和1表示。一个字符在计算机中用8个位表示,8个位组成一个字节。需要将我们通常所习惯的十进制数表示为二进制、八进制或十六进制数来理解对位的操作。位运算符的运算对象必须为整数,C++中所有的位运算符如下:

~(按位求反),<<(左移),

>>(右移),&(按位与),

^(按位异或),|(按位或)【例】将短整型变量a的低8位全变为1,高8位保留原状,应进行的运算是

。答:将a与[0000000011111111]2即[377]8进行按位或即可。本题答案为:a=a|0377。

a:xxxxxxxxyyyyyyyy|0000000011111111xxxxxxxx11111111【例】使短整型变量a的低4位翻转(即0变为1,1变为0),应进行的运算是

。答:将a与[0000000000001111]2即[17]8进行按位异或即可。本题答案为:a=a^017。

a:xxxxxxxxxxxxyyyy^0000000000001111xxxxxxxxxxxxzzzz2.3.7sizeof运算符

sizeof运算符返回其后的表达式或类型标识符所表示的数在内存中所占字节的多少,它有两种形式:

sizeof(类型标识符);•

sizeof表达式;sizeof可以接受的类型标识符很多,如sizeof(int),sizeof(float),sizeof(int*),sizeof(int&),sizeof(int[3])等。对表达式施加sizeof运算符时,返回的是表达式运算结果的数据类型所占据的内存空间。【例】若有floatx;则sizeof(x)和sizeof(float)两种描述

A.都正确 B.都错误

C.前者正确 D.后者正确答:本题答案为:A。2.3.8运算符优先级运算符优先级决定了在表达式中各个运算符执行的先后顺序。高优先级运算符先于低优先级运算符进行运算。如根据先乘除后加减的原则,表达式“a+b*c”会先计算b*c,得到的结果再和a相加。在优先级相同的情形下,则按从左到右的顺序进行运算。当表达式中出现了括号时,会改变优先级。先计算括号中的子表达式值,再计算整个表达式的值。教材中列出了C++的所有运算符集,依优先级从高到低排列。【例】若有定义intnum=7,sum=7;则计算表达式sum=num++,sum++,++num后sum的值为

A.7 B.8C.9 D.10

答:“sum=num++,sum++,++num”是一个逗号表达式,由于逗号运算符的优先级最低,从左向右执行sum=num++、sum++、++num。本题答案为:B。【例】已知intx=6;则执行x+=x-=x*x语句后,x的值是

A.36 B.-60C.60 D.-24

答:先计算x*x=36(x=6),再计算x-=36,即x=x-36=-30,x-=x*x表达式返回x值即-30,最后计算x+=-30,即x=x+(-30)=-60。本题答案为:B。2.3.9表达式可以将表达式理解为用于计算的公式,它由运算符、运算数和括号组成。最简单的表达式只有一个常量或变量,当表达式中有两个或多个运算符时,表达式称为复杂表达式,其中运算符执行的先后顺序由它们的优先级和结合性决定。执行表达式所规定的运算,所得到的结果值便是表达式的值。(1)算术表达式由算术运算符和位操作运算符组成的表达式,其表达式的值是一个数值,表达式的类型由运算符和运算数确定。

(2)逻辑表达式由逻辑运算符组成的表达式。其表达式值类型为逻辑型,一般地,真用1表示,假用0表示。例如,已知intn=2,!n&&5就是一个逻辑表达式。(3)关系表达式由关系运算符组成的表达式。其表达式的值的类型为逻辑型,一般地,真用1表示,假用0表示。例如,已知intn=2,n>=5就是一个关系表达式。

(4)赋值表达式由赋值运算符组成的表达式。例如,已知intn=2,n+=10就是一个赋值表达式。(5)条件表达式由三目运算符组成的表达式。条件表达式的值取决于?号前面的表达式,该表达式的值为非零时,整个表达式的值为:号前面表达式的值,否则为:号后面表达式的值。条件表达式的类型是:号前和后两个表达式中类型高的一个表达式的类型。例如,已知intn=2,n>5?n++:n--就是一个条件表达式。(6)逗号表达式用逗号将若干个表达式连起来组成的表达式。该表达式的值是组成逗号表达式的若干个表达式中最后一个表达式的值,类型也是最后一个表达式的类型。逗号表达式计算值的顺序是从左至右逐个表达式分别计算。例如,已知intn=2,那么n+=3,n=15,n-=10就是一个逗号表达式,该表达式的值为5。【例】若变量已正确定义并赋值,为合法的表达式的是

A.a=a+1; B.a=7+b+c,a++C.int(12.5%2) D.a=a+1=c+b

答:选项A以分号结束,不是表达式;选项B是一个逗号表达式,先将7+b+c赋给a,然后使a增1;选项C中运算符%只能作用于整数,不是表达式;选项D中a+1=c+b不是合法的表达式。本题答案为:B。【例】设x、y、t均为int型变量,则执行语句:x=y=3;t=++x||++y后,y的值为

A.不定值 B.4C.3 D.1

答:在语句t=++x||++y中,++x返回4不为假,故不会执行++y。本题答案为:C。2.3.10数据类型转换

C++中数据类型转换有两类,即隐式类型转换和显式类型转换。

1.隐式类型转换隐式类型转换是由编译器自动完成的类型转换。当编译器遇到不同类型的数据参与同一运算时,会自动将它们转换为相同类型后再进行运算,赋值时会把所赋值的类型转换为与被赋值变量类型一样。隐式类型转换按从低到高的顺序进行,如图2.1所示。图2.1数据类型转换的顺序2.显式类型转换显式类型转换是由程序员显式指出的类型转换,转换形式有两种:

类型名(表达式)

•(类型名)表达式其中,“类型名”是任何合法的C++数据类型,例如float、int等。其功能是通过“类型名”显式地将“表达式”值转换成相应数据类型的值。【例】若有定义:

inta=2,b=3;floatx=3.5,y=2.5;

则下面表达式的值为____。

(float)(a+b)/2+(int)x%(int)y

答:本题答案为:3.500000。2.4复合数据类型复合数据类型包括枚举(enum)、结构体(struct)、共用体(unoin)、位域和用户自定义类型等,此外还有由基本数据类型和复合数据类型引申而来的数据类型,包括数组、指针、引用等。2.4.1枚举类型枚举类型定义了一些整型符号常量的集合,其格式如下:

enum类型名{标识符1,标识符2,…,标识符n};

其中,“标识符1”至“标识符n”表示一些整型符号常量,它们默认由系统赋予整数值:“标识符1”的值为0,“标识符2”的值为1,……,“标识符n”的值为n-1,序列中每个标识符的值比前一个标识符大1。例如:

enumBoolean{No,Yes};//No等于0,Yes等于1

程序员也可以自己定义标识符的值,定义方式是直接在定义语句的标识符后赋值。那些没有显式赋值的枚举值还是比前一个标识符值大1,例如:

enumColor{Red=-2,Yellow,Green=2,Blue};

这样有:Red=-2,Yellow=-1,Green=2,Blue=3。枚举集合前加上的标识符可以代表这一枚举类型,用于变量定义。例如:

enumDay{Mon,Tue,Wed,Thu,Fri,Sat,Sun}; enumDaytoday,tomorrow;//定义2个枚举变量则有:

today=Mon; //合法,today值为0tomorrow=today; //合法,tomorrow值为0intn=today; //合法,n值为0tomorrow=3; //不合法,不能直接赋整数值【例】设有如下枚举类型定义:

enumlanguage{Basic=3,Assembly,Ada=100,COBOL,Fortran};枚举量Fortran的值为

A.4 B.7C.102 D.103

答:在枚举常量Ada指定值为100,所以COBOL的值应为101,Fortran的值应为102。本题答案为:C。2.4.2结构体在C++中可用结构体将不同类型的数据构成一个整体,成为一个新的数据类型,称为结构体类型。结构体类型由各个成员构成,有时也将这些成员称为数据域,简称为域。结构体类型和结构体变量的说明格式如下:

struct[结构体名]

//结构体类型说明

{成员类型成员1;...

成员类型成员n;}[结构体变量名] //结构体变量定义其中,“结构体名”和“结构体变量名”都可以省略。省略前者表示说明了一个无名结构体类型和定义了具有该类型的变量,省略后者表示仅仅说明了一个结构体类型。

例如,说明一个具有姓名和年龄的结构体类型person的语句如下:

structperson {charname[10]; intage; };

上面只是说明了一个名称为person的结构体类型,但没有定义具有该结构体类型的变量,我们可以像使用系统预定义数据类型一样定义结构体类型变量:

structpersonjohn;//定义一个person型变量john

以上两个语句可以合在一起:

structperson {charname[10]; intage; }john;【例】有如下定义:

structdate{intyear;intmonth;intday;};structworklist{charname[20];charsex;structdatebirthday;}person;

对结构体变量person的出生年份进行赋值时,下面正确的赋值语句是

A.year=1958 B.birthday.year=1958C.person.birthday.year=1958D.person.year=1958

答:结构体变量person的birthday又是一个结构体变量,对其year的引用应是person.birthday.year。本题答案为:C。2.4.3共用体共用体的定义形式和用法类似于结构体,但结构体中的每个成员在内存中占有独立的存储位置,而共用体的各个成员共享一块内存,所以,在任意时刻只能有一种数据类型的变量是活跃的。共用体类型和共用体变量的说明格式如下:

union共用体名 //共用体类型说明

{成员类型成员1;...

成员类型成员n;}[共用体变量名]; //共用体变量定义其中,“共用体名”和“共用体变量名”都可以省略。省略前者表示说明了一个无名共用体类型和定义了具有该类型的共用体变量,省略后者表示仅仅说明了一个共用体类型。【例】以下程序的输出结果是

#include<stdio.h>unionmyun{ struct {intx,y,z; }u; intk;}a;main(){ a.u.x=4;a.u.y=5;a.u.z=6; a.k=0; printf("%d\n",a.u.x);}

A.4 B.5C.6 D.0

答:变量a是一个共用体,执行a.k=0语句后覆盖前面的结果。本题答案为:D。2.4.4位域位域是一种紧缩结构体类型,允许我们用更少的空间存放所需要的数据。例如,下面的结构体类型在32位机器上将占用16个字节:

structstatus {unsignedintgood; //只取0或1 unsignedintfail; //只取0或1 unsignedintbad; //只取0或1 intval; //取-100~100 };

其中成员good、fail和bad实际上都只有0和1两个值,完全可以用一个位(bit)来表示。值val取值范围为-100至100,也可用一个完整的整数来记录。可以用位域来重新说明这个结构体类型,它只占用4个字节(至少4个字节或4的整数倍)。【例】以下程序的运行结果是

#include<stdio.h>main(){structst{unsigneda:10;unsignedb:12;unsignedc:2;}x;printf("%d\n",sizeof(x));}A.2 B.3C.24 D.不能通过编译答:位段结构体变量a的总长度为24个位,即3个字节。本题答案为B。2.4.5用typedef定义自己的变量类型在C++中可以利用typedef定义自己的变量类型,其格式如下:

typedef类型说明;

其中,“类型说明”类似于变量说明,只是变量名用类型名代替了,实际上,这等于定义了一个同义词,这种方式与创建一个新的类型是不同的。例如:

typedefintwidth;//定义了新类型width,它实际上是整型

typedefcharstring[10]; //定义了新类型string,它是一个字符数组使用自定义类型和使用系统预定义的类型一样:

widthn; //等价于intn;stringname; //等价于charname[10];使用用户定义类型,应注意以下几点:

使用typedef只能定义各种用户定义类型名,而不能用于定义变量。

用户定义类型相当于原类型的别名。例如:

typedefchar*NAME;NAMEp;等价于:

char*p;

typedef并不是作简单的字符串替换,与#define的作用不同。

typedef定义类型名可嵌套进行。

•利用typedef定义类型名有利于程序的移植,并增加程序的可读性。typedef定义类型步骤:按定义变量方法先写出定义体如inti;将变量名换成新类型名如intINTEGER;最前面加typedef如typedefintINTEGER;用新类型名定义变量如INTEGERi,j;再如:定义数组类型

inta[100];intARRAY[100];typedefintARRAY[100];ARRAYa,b,c;【例】若要说明一个类型名STP,使得定义语句STPs等价于char *s,以下选项中正确的是

A.typedefSTPchar*s; B.typedef*charSTP;C.typedefSTP*char; D.typedefchar*STP;

答:选项A、B和C有语法错误。本题答案为:D。作业练习题22.3、2.4、2.5、2.6

第3章控制语句

算法的基本控制结构有三种:顺序结构、选择结构和循环结构。为此,C++中提供了这三种控制语句,即顺序控制语句、选择控制语句和循环控制语句。3.1顺序控制语句所谓顺序结构,就是按照语句的顺序一条一条地执行。顺序控制语句是一类简单的语句,包括表达式语句、空语句和输入输出语句等。表达式语句是任何一个表达式加上一个分号。在C++程序中,有许多表达式语句。例如,以下都是表达式语句:

a=1+n*2;x=3,y=10,c=1;a>b?a++:b++;

空语句是指只有一个分号的语句(“;”)。可见,空语句是一种不做任何操作的语句。该语句用在一些需要一条语句,但又不做任何操作的地方。3.1.1输出

C++定义了运算符“<<”的iostream类,而“<<”就是用于处理内部类型的输出。使用cout输出流可在屏幕上显示字符和数字。C++提供了一些操纵符,可以直接嵌入到输入/输出语句中来实现I/O格式控制。注意:在使用setprecision和setw操纵符时要在程序开头包含iomanip.h。表3.1列出了几个常用的I/O流类库操纵符。操纵符名含义dec数值数据采用十进制表示hex数值数据采用十六进制表示oct数值数据采用八进制表示ws提取空白符endl插入换行符,并刷新流ends插入空字符setprecision(int)设置浮点数的小数位数(包括小数点)setw(int)设置域宽表3.1常用的I/O流类库操纵符1.显示常数使用cout可以显示字符串和数字,并可显示多个值。

【例】分析以下程序的执行结果。

#include<iostream.h>voidmain(){cout<<1.2345678<<endl;cout<<1<<2<<3<<4<<"\n";cout<<"VisualC++"<<6.0<<endl;}1.23457//只显示6个有效数字1234VisualC++62.八进制和十六进制数的输出在某些情况下,程序需要以八进制或十六进制数的形式输出。C++提供了简单的实现方法:只要在输出流中输出操纵符dec(十进制)、oct(八进制)或hex(十六进制)即可。

注意:一旦使用了进制操纵符,该操纵符的作用域一直连续到程序结束,或者遇到另一个进制操纵符。【例】分析以下程序的执行结果。#include<iostream.h>voidmain(){intn=100;cout<<"十进制:"<<dec<<n<<endl;cout<<"八进制:"<<oct<<n<<endl;cout<<"十六进制:"<<hex<<n<<endl;}

十进制:100

八进制:144

十六进制:643.控制输出宽度

C++提供的setw操纵符可以指定每个数值占用的宽度,即这个字符占用的最小字符长度。当用setw设置的宽度小于实际宽度时,该设置无效。

注意:setw操纵符只对紧跟着它的数值有效。如果要为多个数值设定宽度,必须多次使用setw操纵符。【例】分析以下程序的执行结果。#include<iostream.h>#include<iomanip.h>voidmain(){doublef=123.45;cout<<setw(10)<<1234567890<<endl;cout<<setw(10)<<f<<endl;cout<<setw(8)<<f<<endl;cout<<setw(6)<<f<<endl;cout<<setw(4)<<f<<endl;}执行结果:4.控制输出精度

C++提供的setprecision操纵符可以设置显示数值的精度。

注意:一旦使用了setprecision操纵符,该操纵符的作用域一直连续到程序结束,或者遇到另一个setprecision操纵符。【例】分析以下程序的执行结果。#include<iostream.h>#include<iomanip.h>voidmain(){doubled=123.456789;cout<<d<<endl;cout<<setprecision(7)<<d<<endl;cout<<setprecision(8)<<d<<endl;cout<<setprecision(9)<<d<<endl;}123.457123.4568123.45679123.4567893.1.2输入

C++提供了输入流cin,可以利用输入流cin读取键盘输入的字符和数字,并把它赋给指定的变量。从键盘上输入的数据通过cin接收,再由提取运算符“>>”送到程序指定的变量中。因此,用户输入数据时要避免输入的数据超出指定变量的值域。【例】分析以下程序的执行结果。#include<iostream.h>voidmain(){inti,j;cout<<"ij=";cin>>i>>j;cout<<i<<"+"<<j<<"="<<i+j<<endl;}ij=1245<Enter>12+45=573.2选择控制语句

C++中的选择控制语句有if语句、if...else语句、if...elseif语句和switch语句。3.2.1if语句

if语句用于在程序中有条件地执行某一语句序列,它有如下两种基本语法格式:

if(条件表达式)语句; if(条件表达式) {

语句序列; };【例】以下错误的语句为

A.if(x>y);B.if(x=y)&&(x!=0)x+=y;C.if(x!=y)scanf("%d",&x);elsescanf("%d",&y);D.if(x<y){x++;y++;}

答:if语句的条件必须包含在一个括号中。本题答案为:B。3.2.2if...else语句如果希望在“条件表达式”为真和为假时分别执行不同的语句,则用else来引入条件表达式为假时执行的语句序列,这就是if...else语句,它根据不同的条件分别执行不同的语句序列,其语法形式如下:

if(条件表达式) {

语句序列1; } else {

语句序列2; }【例】为了避免在嵌套的条件语句if-else中产生二义性,C语言规定:else子句总是与

配对。

A.缩排位置相同的if B.同一行上的ifC.其之后最近的if D.其之前最近的if

答:本题答案为:D。【例】以下程序的输出结果是

。#include<stdio.h>main(){intx=2,y=-1,z=2;if(x<y)if(y<0)z=0;elsez+=1;printf("%d\n",z);}A.3 B.2C.1 D.0答:x<y为假,直接执行printf语句。本题答案为:B。【例】以下程序判断输入的年份是否为闰年(凡是能被400整除的,或不能被100整除但能被4整除的年份为闰年)。

#include<iostream.h>voidmain(){ intyear,rem4,rem100,rem400; cout<<"输入年份:"; cin>>year; rem400=year%400; rem100=year%100; rem4=year%4; if((rem400==0)||((rem4==0)&&(rem100!=0))) cout<<year<<"是闰年"<<endl; else cout<<year<<"不是闰年"<<endl;}程序执行:输入年份:2006↙2006不是闰年3.2.3if...elseif语句

if...elseif语句用于进行多重判断,其语法形式如下:

if(条件表达式1)语句1; elseif(条件表达式2)语句2; … elseif(条件表达式n)语句n; else语句n+1;【例】以下程序将用户输入的分数转换成等级:A(≥90),B(80~89),C(70~79),D(60~69),E(<60)。

#include<iostream.h> voidmain() { floatx; cout<<"分数:";cin>>x; if(x>=90)cout<<"A"<<endl; elseif(x>=80)cout<<"B"<<endl; elseif(x>=70)cout<<"C"<<endl; elseif(x>=60)cout<<"D"<<endl; elsecout<<"E"<<endl; }3.2.4switch语句

switch语句也称为开关语句,用于有多重选择的场合,测试某一个变量具有多个值时所执行的动作。switch语句的语法形式为:

switch(整型表达式) { case整型常量表达式1:语句序列1; case整型常量表达式2:语句序列2; … case整型常量表达式n:语句序列n; default:语句n+1; }switch语句的执行顺序是:首先计算switch语句中“整型表达式”的值,然后在case语句中寻找值相等的整型常量表达式,并以此为入口标号,由此开始顺序执行。如果没有找到相等的整型常量表达式,则从“default:”开始执行。使用switch语句应注意下列问题:(1)整型表达式包括字符型或枚举型表达式。(2)各常量表达式的值不能相同,但次序不影响执行结果。(3)每个case分支可以有多条语句,但不必用{}。

(4)每个case语句只是一个入口标号,并不能确定执行的终止点,因此每个case分支的最后应该加break语句,用来结束整个switch结构,否则会从入口点开始一直执行到switch结构的结束点。(5)当若干分支需要执行相同操作时,可以使多个case分支共用一组语句。如:

case1: case2:printf(“case1和2\n”);

注意:可以使用break退出switch语句的执行。如:

case1:printf(“case1\n”);break; case2:printf(“case2\n”);【例】有以下程序:

#include<stdio.h>main(){inta=15,b=21,m=0;switch(a%3){case0:m++;break;case1:m++;switch(b%2){default:m++;case0:m++;break;}}printf("%d\n",m);}

程序运行后的输出结果是

。A.1 B.2C.3 D.4

答:a%3=0,执行m++和printf语句。本题答案为:A。3.3循环控制语句循环控制语句提供重复处理的能力,当某一特定条件为真时,循环语句就重复执行,并且每循环一次,就会测试一下循环条件,如果为假,则循环结束,否则继续循环。

C++支持三种格式的循环控制语句:while、do和for语句。三者可以完成类似的功能,不同的是它们控制循环的方式。3.3.1while语句

while语句的一般形式为:

while(条件表达式)语句;

当“条件表达式”的运算结果为真时,则重复执行“语句”。每执行一次“语句”后,就会重新计算一次“条件表达式”,当该表达式的值为假时,循环结束。【例】设有以下程序段:

intx=0,s=0;while(!x!=0)s+=++x;printf("%d",s);

则______。

A.运行程序段后输出0 B.运行程序段后输出1C.程序段中的控制表达式是非法的 D.程序段执行无限次答:x=0,!x=1,!x!=0为真,执行s+=++x,++x返回1,x=1,s=s+1=1;x=1,!x=0,!x!=0为假,不再执行循环语句。本题答案为:B。3.3.2do语句

do语句的一般形式为:

do

语句;

while(条件表达式);do语句每一次循环执行一次“语句”,然后计算“条件表达式”是否为真,如果是,则继续执行循环,否则结束循环。与while语句不同的是,do循环中的“语句”至少会执行一次,而while语句当条件第一次就不满足时,语句一次也不会被执行。【例】有以下程序段:

intn=0,p;do{scanf("%d",&p);n++;}while(p!=12345&&n<3);

此处do-while循环的结束条件是

A.p的值不等于12345并且n的值小于3B.p的值等于12345并且n的值大于等于3C.p的值不等于12345或者n的值小于3D.p的值等于12345或者n的值大于等于3

答:do-while循环的结束条件为!(p!=12345&&n<3),即p==12345||n>=3。本题答案为:D。3.3.3for语句

for语句通常用于预先知道循环次数的情况,其一般形式为:

for(初始化语句;表达式1;表达式2)语句;

其中,“初始化语句”可以是一个定义语句或表达式语句,一般用于对一组变量进行初始化或赋值。“表达式1”用于控制循环,当它的值为真时,循环会继续下去,而它一旦为假,则终止循环。“表达式2”在每次循环执行完成后执行,一般用于改变控制循环的变量。“语句”在“表达式1”为真时执行。具体来说,for循环的执行过程为:①执行“初始化语句”;②计算“表达式1”的值;③如果“表达式1”的值为真,先执行后面的“语句”,再执行“表达式2”,然后转向步骤②;如果“表达式1”的值为假,则结束循环。【例】以下程序的输出结果是

。#include<stdio.h>main(){inta=0,i;for(i=1;i<5;i++){switch(i) { case0: case3:a+=2; case1: case2:a+=3; default:a+=5; }}pri

温馨提示

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

评论

0/150

提交评论