第2章C++基础知识,candy怎么读

candy 6
第2章C++基础知识 2.1变量和赋值30变量30名称:标识符32变量声明33赋值语句34陷阱:未初始化的变量35编程提示:使用有意义的名称36 2.2输入和输出37使用cout进行输出37include预编译指令和命名空间38转义序列39编程提示:用\n或endl终止每一个程序40格式化带小数点的数字41用cin进行输入42设计输入和输出43编程提示:I/O中的换行43 2.3数据类型和表达式44int类型和double类型44其他数值类型45C++11类型46char类型47bool类型48string类简介48类型的兼容性49算术操作符和表达式50陷阱:除法中的整数52更多赋值语句53 2.4简单控制流程54一个简单的分支机制54陷阱:连续的不等式58陷阱:该用==的时候用了=58复合语句59简单的循环机制61递增操作符和递减操作符63编程实例:信用卡余额64陷阱:无限循环65 2.5程序风格67缩进67注释67为常量命名69 小结71自测题答案72编程练习75编程项目76 30C++入门经典(第10版) 别以为你知道计算机终端是个什么东西。
计算机终端可不是什么乏味的旧电视,前头再摆个打字机。
它是一种接口,使身体和心灵可以和宇宙相连接,并且把其中的一些东西移来移去。
——道格拉斯·亚当斯,《银河系漫游指南》第五卷·基本无害 概述 本章将解释更多的C++示范程序,展示C++语言足够多的细节,便于你写出简单的C++程序。
预备知识 第1章简单介绍了一个C++示范程序,本章将使用那个程序(如果还没有阅读对那个程序的描述,请在继续后面的学习之前阅读它,这对你很有帮助)。
2.1变量和赋值 一旦理解变量在编程中的用法,就可以说理解了编程的精髓。
——艾兹格·戴克斯特拉,“结构化编程”课堂笔记 程序要处理数字和字母之类的数据。
C++和其他常用编程语言一样,使用名为变量的编程构造来命名和存储数据。
变量是编程语言(如C++)的核心,所以要从变量开始介绍C++。
下面将围绕图2.1的程序展开讨论,并解释该程序中的所有元素。
虽然此程序的常规思路应该是很清楚的,但某些细节是新的,需要进行一些解释。
变量 C++变量可容纳一个数字或其他类型的数据。
目前只关心用于存储数字的变量。
这些变量类似于可在上面写数字的小黑板。
黑板上写的数字可以更改,C++变量容纳的数字也可以。
不过,黑板可能不包含任何数字,但变量肯定包含了某个值——可能是以前运行过的程序在内存中留下的垃圾数字。
变量容纳的数字或其他类型的数据称为这个变量的值。
也就是说,变量值是在一个假想的黑板上写下的内容。
图2.1中,numberOfBars,oneWeight和totalWeight是变量。
例如,如果运行程序并提供示范对话中的输入,numberOfBars的值会被设为11,这是通过以下语句来实现的: cin>>numberOfBars; 之后,当程序执行以上语句的另一个拷贝时,变量numberOfBars的值会被更改为12。
稍后会详细解释这是怎样发生的。
第2章C++基础知识31 图2.1一个C++程序 1#include 2usingnamespacestd; 3intmain() 4{
5 intnumberOfBars;//糖的数量
6 doubleoneWeight,totalWeight;//每块糖的重量和总的重量
7 8 cout<<"Enterthenumberofcandybarsinapackage\n";//输入一包糖中有多少块糖
9 cout<<"andtheweightinouncesofonecandybar.\n";//每块糖的重量(盎司) 10 cout<<"Thenpressreturn.\n";//输入后按Enter键 11 cin>>numberOfBars; 12 cin>>oneWeight; 13 14 totalWeight=oneWeight*numberOfBars; 15 16 cout<>numberOfBars; 25 cin>>oneWeight; 26 27 totalWeight=oneWeight*numberOfBars; 28 29 cout<在编程语言中,变量作为内存位置来实现。
编译器将内存位置(参见第1章的讨论)分配给程序中的每个变量名。
0和1形式的变量值存储在为变量分配的内存位置。
例如,在图2.1的程序中,为这三个变量分配的内存位置可能分别是1001,1003和1007。
具体编号取决于计算机、编译器和其他很多因素。
我们不知道、也不关心编译器为变量选择什么内存地址。
可以简单地认为内存位置就是用变量名作为标签。
32C++入门经典(第10版) 程序无法运行 如果无法编译和运行C++程序,请阅读1.3.8节了解如何应对不同的C++编译器和C++环境。
名称:标识符 在示范程序中,首先注意到的可能是变量名比平时在数学课上使用的变量名长。
为了使程序容易理解,务必为变量使用有意义的名称。
变量(或者在程序中定义的其他项目)的名称叫标识符。
标识符以字母或下划线开头,其余字符必须是字母、数字或下划线。
例如,下面的标识符是有效的: xx1x_1_abcABC123z7sumRATEcountdata2Big_Bonus 编译器会接受这些标识符,但前5个不太理想,它们没有表达出用途。
以下标识符则是无效的,编译器拒绝接受: 123x%changedata-1myfirst.cPROG.CPP 前3个之所以无效,是因为不是以字母或下划线开头。
其余3个之所以无效,是因为包含了除字母、数字和下划线之外的其他符号。
C++是对大小写敏感的语言。
也就是说,它会区别对待标识符中的大写和小写字母。
因此,以下3个标识符是不同的标识符,可命名3个不同的变量: rateRATERate 但最好不要在同一个程序中使用这样的变体,因为它们太容易混淆。
虽然C++没有专门要求,但变量名最好全部小写。
预定义标识符(比如main,cin和cout等)则必须全部小写。
本章后面会讲到一些采用大写字母的标识符。
C++标识符长度没有限制,但有的编译器设置了最大允许长度,超出的会被忽略。
标识符 标识符用于命名C++程序中的变量和其他元素。
标识符必须以字母或下划线开头,后续每个字符只能是字母、数字或下划线。
还有一类特殊标识符称为关键字或保留字,它们在C++中有预定义的含义,不能用作变量或其他元素的名称。
附录1列出了所有C++关键字。
你可能会问,为什么定义成C++语言一部分的其他单词未被归为关键字?cin和cout等单词为什么不是关键字?原来,程序员可以重新定义这些单词(虽然这样容易使人混淆)。
但这些预定义的单词确实不是关键字,它们是在C++语言标准要求的库中定义的。
本书后面会讨论库,目前暂时不必关心库的问题。
毫无疑问,为预定义标识符赋予非标准的含义,肯定会产生误导,而且很危险,所以应尽量避免。
最安全、最简单的做法是将所有预定义标识符也视为关键字。
第2章C++基础知识33 变量声明 C++程序中的每个变量都必须声明。
声明变量实际是告诉编译器(最终是告诉计算机):准备在该变量中存储什么类型的数据。
例如,图2.1用两个语句声明了三个变量: intnumberOfBars;doubleoneWeight,totalWeight; 在一个语句中声明多个变量要用逗号分隔不同的变量。
另外,每个语句以分号结尾。
上面两个声明语句中,第一个语句中的int是integer(整数)一词的缩写(但在C++程序里,必须使用缩写形式int,千万不能写全称)。
这行代码将标识符numberOfBars声明为int类型的变量。
这表示numberOfBars的值必须是整数,比如1,
2,-1,0,37或-288。
第二个语句中的double将两个标识符oneWeight和totalWeight声明为double类型的变量。
double类型的变量可存储带小数部分的值,如1.75或-0.55。
变量能容纳的数据的种类称为这个变量的类型,类型的名称(如int或double)称为类型名称。
变量声明所有变量必须在使用之前声明。
变量声明语法如下: 语法 Type_NameVariableName1,VariableName2,…; 示例intcount,numberOfDragons,numberOfTrolls;doubledistance; 命名规范命名规范是指标识符(比如变量名)的一套命名规则。
本书变量名以小写字母开头。
如变量名由多个单词复合,之后各单词以大写字母开头。
这个规范称为camelCase。
C风格的规范要求各单词以下划线连接。
还有的规范要求在变量名中指定变量类型。
C++程序的每个变量都必须在使用前声明。
有两个非常自然的位置可供声明变量:刚好在使用变量之前,或者在程序main部分的起始处,也就是在以下两行代码之后: intmain(){ 总之,选择能使程序变得更清晰的位置。
变量声明提供了编译器实现变量所需的信息。
前面说过,编译器将变量实现为内存位置,而变量的值保存在为这个变量分配的内存位置中。
变量的值被编码为一连串0和
1。
不同类型的变量需要不同大小的内存位置,还需要用不同的编码方式把它们的值编码为一连串0和
1。
计算机用一种方式将整数编码为一连串0和
1,用另一种方式编码带有小数部分的数字,再用另一种方式将字母编码为一连串0和
1。
变量声明实际是告诉编译器(最 34C++入门经典(第10版) 终是告诉计算机)两点:第
一,应该为一个变量分配多大的内存位置;第
二,用哪种编码方式将变量的值表示为一连串0和
1。
语法和语义 编程语言(或其他任何语言)的语法(syntax)指该语言的一套语法规则。
例如,谈论变量声明的语法时(参见上一个小结框“变量声明”),实际是说为了写一个具有良好格式的变量声明,需要遵循哪些规则。
遵循了C++的所有语法规则,编译器就肯定接受你的程序。
当然,这只能保证程序有效。
虽然能保证程序能做某事,但不能保证它做的是你真正想做的事情。
语义(semantics)是指程序运行时所做事情的含义。
程序的语法和语义都应正确。
赋值语句 更改变量值最直接的方式就是使用赋值语句。
赋值语句是表示“将变量设为指定值”
的计算机指令。
以下赋值语句摘自图2.1的程序: totalWeight=oneWeight*numberOfBars; 它要求计算机将totalWeight的值设为两个变量(oneWeight和numberOfBars)中的数字的乘积(第1章讲过,*是C++中的乘号)。
赋值语句总是由等号左侧的变量和等号右侧的表达式组成。
赋值语句以分号结尾。
等号右侧的表达式可以是变量、数字或者由变量、数字和算术操作符(如*和+)构成的较复杂的表达式。
赋值语句指示计算机对等号右侧的表达式进行求值(计算这个表达式的值),并把等号左侧的变量的值设为求值的结果。
多研究一些例子有助于掌握赋值语句的工作原理。
可用任何算术操作符代替乘号(*)。
例如,以下语句也是有效的赋值语句: totalWeight=oneWeight+numberOfBars; 该赋值语句与示范程序的赋值语句一样,区别在于执行加法而非乘法。
它将totalWeight的值设为两个变量值(oneWeight和numberOfBars)之和。
当然,如果在图2.1中进行这样的改动,程序虽会运行,但会给出不正确的输出。
赋值语句的等号右侧的表达式可以是另一个变量。
以下语句使变量totalWeight的值变得和变量oneWeight一样: totalWeight=oneWeight; 在图2.1的程序中进行上述修改,程序给出的一包糖的重量将错误地小于实际值(假定一包糖内不止一块糖)。
但在其他程序中,这样赋值可能是有意义的。
作为另一个例子,以下赋值语句将numberOfBars的值变成37: numberOfBars=37; 代码中的实际数字(如本例的37)称为常量。
和变量不同,常量的值不能改变。
由于变量值可以随时间更改,同时赋值操作符是更改其值的手段,所以赋值语句的含义必须考虑到时间因素。
在时间上,首先求值的是等号右侧的表达式。
然后,等号左侧的 第2章C++基础知识35 变量的值被更改为那个表达式的求值结果。
这就意味着一个变量可以同时出现在赋值操作符的两侧。
例如以下赋值语句: numberOfBars=numberOfBars+3; 初学者可能不解其意。
如果像普通的句子那样读,就是“numberOfBars等于numberOfBars加
3。
”但实际含义是“让numberOfBars的新值等于numberOfBars的旧值加
3。
”在C++中,等号的用法与日常语言或数学中的等号不同。
赋值语句 赋值语句中,等号右侧的表达式先求值,该值赋给等号左侧的变量。
语法Variable=Expression;示例distance=rate*time;count=count+2; 陷阱:未初始化的变量 除非程序为变量赋值,否则变量不包含有意义的值。
例如,如果变量minimumNumber既没有放在一个赋值语句的左侧而被赋值,也没有通过其他手段来赋值(比如用cin语句赋一个由用户输入的值),以下语句就是错误的: desiredNumber=minimumNumber+10; 这是由于minimumNumber不包含有意义的值,所以等号右侧的整个表达式也不会产生有意义的值。
如变量(比如minimumNumber)未被赋值,就说它未初始化。
事实上,这比minimumNumber不包含任何值还要糟。
未初始化的变量(比如minimumNumber)将包含“垃圾值”。
未初始化的变量的值由留在其内存位置中的0,1序列来决定(可能是由用过该内存位置的上一个程序留下的)。
因此,如果程序运行两次,未初始化的变量每次都可能获得不同的值。
只要程序为完全相同的输入数据产生了两个不同的输出,而且程序本身未进行任何修改,就应该怀疑其中含有未初始化的变量。
为了避免出现未初始化的变量,一个办法是在声明变量的同时初始化。
这可通过添加一个等号和一个值来完成,如下所示: intminimumNumber=3; 它除了将minimumNumber声明为int类型的变量,还将minimumNumber的值设为
3。
像这样在同一行声明并初始化时,可以使用涉及运算(比如加法或乘法运算)的一个更复杂的表达式。
然而,最常见的还是使用简单的常量来初始化。
可在一个声明内列出多个变量,同时初始化其中的部分或全部变量,或者一个都不初始化。
例如,以下语句声明了三个变量,但只初始化其中两个: doublerate=0.07,time,balance=0.0; C++允许采用另一种方式在声明变量的同时初始化它。
以下语句等价于刚才的声明: 36C++入门经典(第10版) doublerate(0.07),time,balance(0.0); 具体是在声明的同时初始化,还是以后再初始化,要取决于实际情况。
你选择的方式 应该使程序更容易阅读。
■ 声明时初始化变量 可在声明变量的同时初始化它(向它赋值)。
语法 Type
_NamevariableName1=Expression_for_Value_1,variableName2=Expression_for_Value_2,...; 示例intcount=0,limit=10,fudgeFactor=2;doubledistance=999.99; 声明变量同时初始化的另一种方式:Type_NamevariableName1(Expression_for_Value_1), variableName2(Expression_for_Value_2),...; 示例intcount
(0),limit(10),fudgeFactor
(2);doubledistance(999.99); 编程提示:使用有意义的名称 变量名和其他名称至少应该让人联想到它们所命名的事物的含义或用途。
有意义的变量名可以使程序更容易理解。
所以,以下语句: x=y*z; 最好更改为: distance=speed*time; 两个语句作用一样,但第二个更容易理解。
√自测题
1.给出变量feet和变量inches的声明。
两个变量都是int类型,都在声明中初始化为
0。
请同时使用前面介绍的两种初始化方式。

2.给出变量count和变量distance的声明。
count是int类型,初始化为0;distance是double类型,初始化为1.5。

3.给出C++语句,将变量sum的值更改为变量n1和n2的值之和。
所有变量都是int类型。

4.给出C++语句,使变量length的值增大8.3。
变量length已经声明为double类型。

5.给出C++语句,将变量product的值更改为它的旧值乘以变量n的值。
这些变量都是int类型。

6.写程序来输出虽已声明但尚未初始化的五六个变量的值。
编译并运行。
会输出什么?请说明原因。

7.为以下每个变量提供有意义的名称:a.一个用于保存车速的变量;b.一个用于保存小时工每小时薪酬的变量;c.一个用于保存一次考试的最高分的变量。
第2章C++基础知识37 2.2输入和输出 垃圾入,垃圾出。
——程序员的口头禅 C++程序可采取几种不同的方式执行输入和输出。
我们描述其中的一种,即“流”。
输入流是提供给计算机并由程序使用的一系列输入。
“流”这个词表明程序将以相同的方式处理所有输入,无论这些输入是从什么地方来的。
换言之,程序看到的只是输入流本身,看不到流的来源。
好比山间一条小溪,溪水在你面前流过,而你不知道它来自哪里。
本节假设输入来自键盘。
第6章将讨论程序如何从文件读取输入。
到时就会知道,从键盘读取输入的语句也可用于从文件读取。
类似地,输出流是程序生成的一系列输出。
本节假设输出到终端屏幕(第6章将讨论如何输出到文件)。
使用cout进行输出 可以使用cout将变量值和文本字符串输出到屏幕。
变量和字符串可组合输出。
以图2.1的下面这行代码为例: cout<注意,不需要为每个输出项都单独使用单词cout。
可以列出所有输出项,在每一项之前附加箭头符号<<。
上述cout语句等价于以下两个cout语句: cout<两个<(小于)符号应连续输入,中间不要有空格。
箭头符号<<通常称为插入操作符。
整 个cout语句以分号结尾。
只要连续出现了两个cout语句,就可以将其合并成一个较长的cout语句。
以图2.1 的以下两行代码为例: cout<一种较好的做法是将上述较长的cout语句改写成如下形式: cout<但是,凡是能插入空格的地方都能另起一行。
计算机接受任何合理的间隔与换行风格,但上例和本书的其他示范程序是你应该学习的“好榜样”。
一个较好的策略是,针对直观上可视为一个整体的每组输出都使用一个cout。
注意,每个cout都只对应一个分号,即使一个cout语句被拆分成若干行。
在图2.1的程序中,特别注意要输出的引号字符串。
注意,要输出的字符串必须包含在一对双引号内。
每个双引号都是一个单独的字符(按一次键即可输入),不要连续键入两个单引号来取代它。
还要注意,字符串两端使用的是同一个双引号,没有独立的左引号和右引号。
还要注意引号内的空格。
计算机不会在cout输出的内容前后自动添加空格。
因此,示例中的引号字符串通常都会以一个空格开始和/或结束。
空格防止不同的字符串和数字紧挨在一起。
如果只想输出空格,就使用只包含空格的字符串。
如下所示: cout<除非告诉计算机换行,否则它会将所有输出放到同一行。
取决于计算机屏幕设置,这可能导致输出时任意换行①,或者一行的剩余内容跑到屏幕外面。
注意\n是在引号内部使用的。
在C++中,“换行”被视为一个特殊字符(特殊符号)。
在引号字符串内,这个特殊字符要拼写成\n。
注意,符号\和n之间没有空格。
虽然这个特殊字符在输入时要使用两个符号,但C++将\n视为一个字符,并称之为换行符。
include预编译指令和命名空间 我们所有程序都以下面这两行代码开始: #includeusingnamespacestd; 这两行使iostream库进入可用状态。
cin和cout的定义就包含在这个库中。
所以,假如程序使用了cin或cout,就应在程序文件起始位置包含上述两行代码。
下面这一行代码称为include预编译指令。
它将iostream库“包含”到程序中,使程序能使用cin和cout: #include cin和cout在一个名为iostream的文件中定义,以上include指令相当于将那个文件复制到程序中。
第二行代码比较复杂,三言两语很难说清。
C++使用命名空间组织名称。
命名空间是很多名称(比如cin和cout)的集合。
通过以下方式指定命名空间的语句称为using预编译指令: ①例如,单词“word”的“ord”部分可能跑到下一行。
——译注 第2章C++基础知识39 usingnamespacestd; 这个特定的using指令表明程序准备使用std(指standard)命名空间。
这意味着你使用的名称具有std命名空间为其定义的含义。
这儿的重点在于,cin和cout等名称在iostream中定义时,它们的定义指出它们在std命名空间中。
所以,要使用cin和cout等名称,就要告诉编译器你准备“usingnamespacestd;”。
对于命名空间并不需要了解太多(就目前而言),但简单澄清一下,有助于解除你在使用命名空间时可能产生的一些困惑。
C++之所以有命名空间,是因为有太多的东西需要命名。
结果就是可能有两个或更多的项同名。
换句话说,一个名称可能具有两个不同的定义。
为消除歧义,C++将不同的项划分到不同的集合中,确保同一个集合(即同一个命名空间)中没有任何两个项同名。
注意,命名空间并不只是一个名称集合。
它代表了一个C++代码主体,其中指定了某些名称的含义(比如一些定义和/或声明)。
命名空间的作用是将所有C++名称规范划分成不同的集合(称为命名空间),使命名空间内的每个名称在那个命名空间中都只有一个“规范”(一个定义)。
命名空间对名称进行划分,但和那些名称配合的还有大量C++代码。
可以使用两个命名空间中的两个同名元素吗?答案是肯定的,而且并不复杂,但那是本书后面要讲的一个主题。
目前不需要这样做。
有的C++版本使用include预编译指令的一种古老形式(没有任何usingnamespace): #include 使用以下语句时,如果程序无法编译或者不能运行: #includeusingnamespacestd; 请尝试将上述两行代码统一更换为如下形式: #include 但如果程序要求使用iostream.h(而不是iostream),则表明你使用的是老版本的C++编译器。
升级一下吧。
转义序列 字符前的符号\告诉编译器:\之后的字符具有特殊含义,不能沿用其字面含义。
这样的一个字符序列称为转义序列。
转义序列肯定由两个字符构成,而且两个字符之间没有空格。
C++定义了几个转义序列。
如果希望在一个字符串常量中插入反斜杠\或插入双引号",则必须使用\"来转变"的原有功能(结束一个字符串常量),或者使用\\来转变\的原有功能(转义)。
\\向编译器表明你需要一个真正的反斜杠\,而不是一个转义序列。
\"表明需要一个真正的双引号,而不是结束一个字符串常量。
如果在字符串常量中出现未定义的转义序列(比如\z),有的编译器会返回一个z,有的则会报错。
ANSI标准规定,对于未定义的转义序列,其行为是“未定义”的。
所以,编译器的设计者可采用自己觉得方便的任何方式处理它。
其后果是,如果在代码中使用了未定义的转义序列,就失去了“可移植性”。
因此,不要使用任何未定义的转义序列。
下面列 40C++入门经典(第10版) 出了C++定义的部分转义序列: 换行符 \n 水平制表符\t 响铃符 \a 反斜杠 \\ 双引号 \" 此外,C++11支持所谓的原始字符串字面值(rawstringliterals),它适合有太多字符需 要转义的情况。
该格式要求字符串以R开头,而且字符串内容要放到一对圆括号中。
例如, 以下代码输出字符串字面值"c:\files\"。
cout<\n和endl应该如何选择呢?一个较好的依据是:如果\n可以放到一个较长的字符串的末尾,就像下面这样使用\n: cout<<"Fuelefficiencyis"<另一种方法是通过endl来换行,如下所示: cout<<"Youhavedefinitelywon"<如果程序输出的最后一项是字符串,就在该字符串的末尾添加一个\n;如果不是,就将输出endl作为程序的最后一个动作。
这样做有两个目的:有的编译器不输出程序中的最后一行,除非在末尾包含一个换行指令。
在另一些系统上,即使没有这个最后的换行指令,程序也能正常运行,但运行下一个程序时,它会将自己的第一行输出与上一个程序的最后一行输出混在一起。
即使这两个问题在你的 第2章C++基础知识41 系统上都不存在,在程序末尾添加一个换行指令,起码也能使程序具有更强的移植性。
■ 格式化带小数点的数字 计算机输出double类型的值时,格式可能与你预期的不同。
例如,下面这个简单的cout语句就会产生很多种不同的输出: cout<<"Thepriceis$"<可以在程序中插入一个“魔法配方”,指定含有小数点的数字(比如double类型的数字)以日常生活中习惯的方式来输出。
换言之,可以确切地指定小数位数。
例如,为了显示两位小数,需要以下“魔法配方”: cout.setf(ios::fixed);cout.setf(ios::showpoint);cout.precision
(2); 在程序中插入上述3个语句,后续的任何cout语句都会按你指定的格式输出double类型的值。
换言之,小数点之后刚好2位。
例如,假设以下cout语句出现在上述“魔法配方”之后的某个地方,并假设price的值为78.5: cout<<"Thepriceis$"<2,从而指定不同的小数位数。
甚至能用int类型的变量代替
2。
这个“魔法配方”将在第6章进一步解释。
现在只需将其视为一长串指令,目的是告诉计算机你想以什么格式输出含小数点的数字。
要更改小数位数,使程序中不同的值输出不同的小数位数,可以重复使用这个“魔法配方”,用其他数字代替
2。
但是,重复这些“魔法配方”时,只需重复其中的最后一行。
假如该“魔法配方”已在程序中出现过一次,那么只需添加下面这一行,即可让后续的所有double类型的变量输出5位小数: cout.precision
(5); 42C++入门经典(第10版) 输出double类型的值 在程序中插入以下“魔法配方”,后续所有double类型(或允许保留小数的其他类型)的数字将以日常生活中最习惯的方式来输出,即保留两位小数: cout.setf(ios::fixed);cout.setf(ios::showpoint);cout.precision
(2); 可用其他任何非负的整数代替其中的
2,从而指定不同的小数位数。
甚至能用int类型的变量代替
2。
用cin进行输入 使用cin输入时,方式与使用cout输出差不多。
两者语法相似,区别在于cin代替了cout,而且箭头方向相反。
例如,在图2.1的程序中,numberOfBars和oneWeight变量由以下cin语句来填充(同时给出了cout语句,告诉用户应该如何操作): cout<<"Enterthenumberofcandybarsinapackage\n";cout<<"andtheweightinouncesofonecandybar.\n";cout<<"Thenpressreturn.\n";cin>>numberOfBars;cin>>oneWeight; 可以在一个cin语句中列出多个变量。
所以,以上代码可以重写为以下形式: cout<<"Enterthenumberofcandybarsinapackage\n";cout<<"andtheweightinouncesofonecandybar.\n";cout<<"Thenpressreturn.\n";cin>>numberOfBars>>oneWeight; 如果愿意,还可将上述cin语句拆成以下两行代码: cin>>numberOfBars>>oneWeight; 注意,和cout语句一样,每个cin只对应一个分号。
程序抵达cin语句时,它会等待用户从键盘输入。
它将第一个变量设为从键盘输入的 第一个值,第二个变量设为从键盘输入的第二个值,依此类推。
但除非按Enter键,否则程序不会真正读取输入。
利用这个设计,可在输入一行内容时按Backspace键纠错。
输入的各个数字必须以一个或多个空格或者以一个换行符来分隔。
例如,假定要输入两个数字12和
5,但输入时没有用空格分隔它们,计算机就认为输入的是一个数字,即125。
使用cin语句时,计算机会跳过任意数量的空格或换行符,径直找到下一个输入值。
因此,无论你用一个还是多个空格,甚至用一个换行符来分隔,都是无关紧要的。
cin语句cin语句将变量设为从键盘键入的值。
语法cin>>Variable_1>>Variable_2>>…; 示例cin>>number>>size;cin>>timeToGo >>pointsNeeded; 第2章C++基础知识43 设计输入和输出 输入和输出通常称为I/O,是程序中用户看得见的部分。
I/O设计不佳,就无法取悦于用户。
计算机执行cin语句时,它希望收到从键盘输入的数据。
用户不输入数据,计算机会一直等下去。
程序必须提示用户什么时候应该输入数字(或其他数据项)。
计算机不会自动要求输入,所以示范程序包含了以下输出语句: cout<<"Enterthenumberofcandybarsinapackage\n";cout<<"andtheweightinouncesofonecandybar.\n";cout<<"Thenpressreturn.\n"; 这些输出语句提示用户输入。
程序希望获取输入时一定要明确提示。
从终端输入数据时,输入的内容会在屏幕光标位置出现。
虽然如此,始终应该在程序 终止之前,主动显示输入的值。
这称为回显输入,作用是让用户检查输入是否被正确读取。
之所以要回显,是因为有时在屏幕上看起来没有问题的输入不一定能被计算机正确读取。
例如,其中可能含有被忽视的打字错误或其他问题。
通过回显输入,能对输入数据的完整性进行测试。
编程提示:I/O中的换行 可在同一行输出和输入,而且对用户而言,这有时能产生更友好的界面。
如果在最后一个提示行末尾省略\n或endl,用户的输入就会在这个提示行上出现。
例如,假设使用以下提示和输入语句: cout<<"Enterthecostperperson:$";cin>>costPerPerson; 程序执行cout语句时,屏幕上将出现以下提示: Enterthecostperperson:$ 用户输入的数据将在同一行上出现,如下所示: Enterthecostperperson:$1.25 ■ √自测题
8.写一个输出语句在屏幕上生成以下消息①: TheanswertothequestionofLife,theUniverse,andEverythingis42.
9.写一个输入语句,使用从键盘输入的值来填充int类型的变量theNumber。
在输入语句前添加一个提示语句,提示用户输入一个整数。
①“那个伟大问题的答案„„关于生命、宇宙以及一切„„是„„42。
”这句话来自道格拉斯•亚当斯的科幻名著《银河系漫游指南》。
——译注 44C++入门经典(第10版) 10.输出double类型的数字时,在程序中添加什么语句能确保这种类型的值以正常格式输出,并具有3个小数位。
11.写一个完整的C++程序,要求在屏幕上显示Helloworld。
不要求该程序具备其他功能。
12.写一个完整的C++程序,要求读入两个整数,并输出两个整数之和。
一定要提示输入,回显输入,并 清楚说明输出的是什么。
13.写一个输出语句来输出一个换行符和一个制表符。
14.写一个小程序,声明double类型的变量one,two,three,four和five,分别初始化为1.000, 1.414,1.732,2.000和2.236。
写一些输出语句来生成以下表格。
使用制表符转义序列\t来对齐不同的列。
如果还不熟悉制表符,请在做这道题的时候试验它。
制表符相当于打字机上的一个机械跳格位置,会导致输出从下一列(栏)开始,两列间距通常是8个空格的倍数。
许多编辑器和大多数字处理程序都允许调整制表位。
我们的输出不调整。
输出应该如下所示:NSquareRoot11.00021.41431.73242.00052.236 2.3数据类型和表达式 他俩没戏。
他不是她喜欢的类型。
——鸡尾酒会上的闲言碎语 int类型和double类型 2和2.0在概念上固然是同一个数字,但C++将它们视为不同类型。
2是int类型,2.0是double类型,因为后者包含了小数部分(即使小数部分为0)。
再次强调,计算机编程所涉及的数学概念与数学课上学到的略有区别。
计算机的一些实际问题造成计算机中的数字有别于这些数字的抽象定义。
C++中,整数的行为和你预期的一样。
int类型保存的就是整数。
但double类型要麻烦一些。
由于double类型只能存储有限位数的数字,所以计算机将double类型的值保存为近似值。
相反,int类型的值则作为精确值来保存。
double值的具体精度在不同计算机上是不同的。
但无论如何,double值的精度至少能达到14位。
这个精度对于大多数应用程序已经足够。
不过,即使在一些简单的情况下,它也有可能造成不易察觉的问题。
因此,如果已知某个变量保存的值是整数,而且大小在计算机能接受的范围之内,就最好把它声明为int。
double数字常量在书写时有别于int数字常量。
int常量绝对不能包含小数点。
double常量则有两种写法。
对于double常量,最简单的形式就是日常生活中的写法(带小数)。
采用这种写法,double常量必须包含小数点。
double和int常量有一个共同点:C++的任何数字都不能包含逗号。
double类型的常量的一种更复杂的写法称为科学记数法或浮点记数法,特别适合表达 第2章C++基础知识45 非常大的数和非常小的小数。
例如,数字3.67×1017相当于367000000000000000.0,在C++中最好表示成常量3.67e17。
再如数字5.89×10-
6,它相当于0.00000589,在C++中最好表示成常量5.89e-
6。
e代表exponent(指数)。
e-6相当于“乘以10的-6次方”。
之所以要使用e记数法,是因为通常无法直接通过键盘输入作为上标的指数。
e后面的数字指出了两点:第
一,小数点的移动方向;第
二,要移多少位。
例如,要把3.49e4变成一个没有e的数字,需要让小数点右移4位,得到34900.0,这是同一个数的另一种写法。
如果e后面的数字为负,小数点就左移指定位数,必要时插入
0。
所以,3.49e-2相当于0.0349。
e之前的数字可包含小数点,但这并非必须。
但e之后的指数绝对不能有小数点。
由于计算机内存有限,所以数字通常只能用数量有限的字节来存储(也就是说,只能占用有限的存储空间)。
所以数字大小也是有限的,而且这一限制因数字的类型而异。
double类型的最大值肯定大于int类型的最大值。
目前大多数C++实现都规定int类型的值不得超过2147483647,而double类型的值不得超过10308。
double缘起 为什么带小数的数是double类型?是否还有single类型,大小只有double的一半?答案是既错又对。
过去,许多编程语言用两种类型表示带小数的数。
一种类型使用内存较少,但不太精确(也就是说,它不允许非常多的有效位)。
第二种类型占用的内存是第一种类型的两倍(double由此而来),所以精度更高。
与此同时,它还支持更大的数(尽管程序员对精度的关心远胜于大小)。
使用两倍内存的这类数字称为“双精度”数字,使用较少内存的则称为“单精度”数字。
在C++中,根据这一传统约定,与双精度类型对应的类型称为double类型,与单精度对应的则是float类型。
C++还为带小数的数提供了第三种类型,即longdouble类型。
这些类型将在下一小节描述。
不过,本书没有任何场合需要使用float和longdouble类型。
其他数值类型 除了int和double,C++还有其他数值类型,图2.2总结了其中一部分。
图2.2部分数值类型 类型名称 占用的内存 取值范围 精度 short(或shortint) 2字节 -32767~32767 (不适用) int 4字节 -2147483647~2147483647 (不适用) long(或longint)floatdoublelongdouble 4字节4字节8字节10字节 -2147483647~2147483647约10-38~1038约10-308~10308约10-4932~104932 (不适用)7位15位19位 <本表格仅供参考,目的是让你体会不同类型的区别。
在具体每个人的系统上,情况可能不同。
“精度” 是指有效位数,其中包括小数点前的位。
float,double和longdouble类型显示的取值范围是正数 范围。
负数也有一个类似的范围,但要在每个数字之前添加负号> 46C++入门经典(第10版) 不同数值类型允许不同取值范围,也允许或高或低的精度。
图2.2给出的占用内存、取值范围和精度仅供参考,目的是让你体会各种类型的区别。
这些指标因系统而异。
在你的系统上,情况可能不同。
虽然有的类型要用两个单词来拼写,但在声明这些类型的变量时,与声明int及double类型的变量并无区别。
例如,以下语句声明一个longdouble类型的变量: longdoublebigNumber; 类型名称long和longint代表同一个类型。
所以,以下两个声明是等价的: longbigTotal;longintbigTotal; 当然,程序只能在上述两个声明中选择一个来声明变量bigTotal。
但具体选择哪个无关紧要。
还要记住,类型名称long等价于longint,而不是等价于longdouble。
用于表示整数的类型(比如int和其他类似的类型)统称为整数类型或者整型。
用于表示带小数点的数字的类型(比如double和其他类似类型)则统称为浮点类型或者浮点型。
之所以称为“浮点”,是因为计算机在存储像392.123这样正常写法的数字时,首先会将数字转换成与e记数法类似的一种形式(本例是3.92123e2)。
计算机执行这种转换时,小数点会“浮动”(也就是移动)到一个新位置。
虽然C++支持其他数值类型,但本书只用到了int和double,偶尔用一下long。
对于大多数简单应用程序,除了int和double,其他任何类型都派不上用场。
需要大整数的程序可考虑long。
C++11类型 整型的大小在不同计算机上可能不一样。
例如,32位机器的整数可能是4字节,而64位机器可能是8字节。
如需确定一个整型的取值范围,这就可能成为问题。
C++11增加了新整型来解决问题。
新整型指定了确切大小以及是否有符号。
这些类型通过包含来使用。
图2.3列出了部分类型。
本书主要使用传统int和long。
但如果要指定确切大小,请考虑使用C++11类型。
图2.3部分C++11定宽整型 类型名称 占用的内存 取值范围 int8_tuint8_tint16_tuint16_tint32_tuint32_tint64_tuint64_tlonglong 1字节1字节2字节2字节4字节4字节8字节8字节至少8字节 -128~1270~255-32768~327670~65535-2147483648~2147483647 0~4294967295-9223372036854775808~92233720368547758070~18446744073709551615 第2章C++基础知识47 C++11还提供auto类型,能根据等号右侧的表达式推断变量类型。
例如,以下代码定义名为x的变量,它的数据类型由expression的求值结果决定。
autox=expression; 该功能目前效果不彰,但以后定义自己的数据类型时可利用它简化代码。
C++11还增加了判断变量或表达式类型的功能。
decltype(expr)是变量或表达式 expr的已声明类型,可在声明新变量时使用。
例如: intx=10;decltype(x*3.5)y; 上述代码声明y的类型和x*3.5一样。
表达式x*3.5的结果是double,所以y被声明为double。
视频讲解:C++11FixedWidthIntegerTypes char类型 我不想让你觉得计算机和C++只会执行数值计算。
接下来要介绍一种非数值类型。
以后还会遇到其他更复杂的非数值类型。
char(character的缩写)类型的值表示单独一个符号,比如字母、数字或标点符号。
在书籍和日常对话中,经常将这种类型的值称为字符。
在C++程序中,这种类型必须拼写成缩写形式char。
例如,char类型的变量symbol和letter可以像下面这样声明: charsymbol,letter; char类型的变量可容纳键盘上的任何单独字符。
所以,变量symbol可容纳一个'A'、一个'+'或者一个'a'。
注意,字母大写和小写形式被视为不同字符。
使用cout输出的双引号中的文本则称为字符串值。
例如,下面就是一个字符串,它来自图2.1的程序: "Enterthenumberofcandybarsinapackage\n" 注意,字符串常量放到双引号内,而char类型的常量放到单引号内。
两种引号含义不同。
例如,'A'和"A"不同。
'A'是char值,可存储到char类型的变量中。
而"A"是字符串值。
虽然这个字符串恰好只包含一个字符,但这一事实并不能使"A"成为char。
还要注意,无论字符串还是字符,左右两个引号是一样的(都是"或')。
图2.4演示如何使用char类型。
注意在第一个和第二个姓名首字母之间输入了一个空格。
但程序会跳过空格,将字母B作为输入的第二个字母来读取。
通过cin将输入读入char类型的变量时,计算机会忽略所有空白间隔和换行符,直到遇到第一个非空白字符,并将其读入变量。
输入中有无空白字符(比如空格、制表符等)对计算机没有区别。
运行图2.4的程序,无论在两个姓名首字母之间插入一个空格(如示范对话所示),还是连续输入两个首字母(不插入空格,即直接输入JB),结果都是一样的。
图2.4char类型 1#include2usingnamespacestd; 48C++入门经典(第10版) 3intmain() 4{
5 charsymbol1,symbol2,symbol3; 6789101112131415} cout<<"Entertwoinitials,withoutanyperiods:\n";//输入两个姓名首字母,不要加点号cin>>symbol1>>symbol2;cout<<"Thetwoinitialsare:\n";cout<该类型由ISO/ANSI(国际标准化组织/美国国家标准化组织)于1998年增补到C++语言中。
bool类型的表达式称为布尔(Boolean)表达式,这一名称源于英国数学家eBoole(1815-1864),他是数学逻辑规则的奠基人。
布尔表达式的求值结果只有两个:true或false。
布尔表达式在分支和循环语句中使用。
2.4节更详细地讨论布尔表达式和bool类型。
string类简介 虽然C++缺乏原生数据类型来直接操作字符串,但在string类的帮助下,可采取和原生数据类型相似的方式处理字符串。
类和原生数据类型的区别在第10章讨论。
第8章更详细地讨论string类。
使用string类必须先包含string库: #include 程序还必须包含以下代码,通常放到文件起始处: usingnamespacestd; 声明string类型的变量和声明int或double类型的变量一样。
例如,以下代码声明string类型的一个变量,并在变量中保存单词"Monday": stringday;day="Monday"; 如图2.5所示,可用cin将数据读入字符串。
在两个字符串之间使用“+”符号可将两个字符串连接成一个更长的。
例如以下代码: stringday,day1,day2;day1="Monday"; 第2章C++基础知识49 day2="Tuesday";day=day1+day2; 会连接成以下字符串: "MondayTuesday" 注意,连接两个字符串不会自动添加空格。
这样的空格只能显式添加,如下所示: day1+""+day2 用cin将输入的内容读入string变量时,除非遇到空白字符,否则计算机会一直读下去。
空白字符是指在屏幕上所有显示为空白的字符,包括空格、制表符和换行符'\n'。
这意味着不能输入含空格的字符串,否则就会出错。
图2.5的示范对话2演示了一个例子。
在本例中,用户试图输入"Mr.Bojangles"作为宠物名,但字符串只能读到"Mr."为止,因为下个字符是空格。
"Bojangles"字符串被程序忽略,但假如有另一个cin语句,那么接下来就会读入它。
第8章将介绍输入含空格字符串的一个技术。
图2.5string类 1#include 2#include 3usingnamespacestd; 4intmain() 5{
6 stringmiddleName,petName;
7 stringalterEgoName;
8 //ego是拉丁文“我”的意思,alterego就是“另一个我”,或者说“知己”
9 cout<<"Enteryourmiddlenameandthenameofyourpet.\n"; 10 cin>>middleName; 11 cin>>petName; 12 13 alterEgoName=petName+""+middleName; 14 15 cout<<"Thenameofyouralteregois"; 16 cout<1 Enteryourmiddlenameandthenameofyourpet.ParkerPippenThenameofyouralteregoisPippenParker. 示范对话
2 Enteryourmiddlenameandthenameofyourpet.ParkerMr.BojanglesThenameofyouralteregoisMr.Parker. 类型的兼容性 一种类型的值一般不能存入另一种类型的变量。
例如,大多数编译器对以下语句报错: intintVariable;intVariable=2.99; 50C++入门经典(第10版) 这是因为类型不匹配。
常量2.99是double类型,变量intVariable是int类型。
遗憾的是,并非所有编译器都以相同的方式响应上述赋值语句。
有的显示错误消息,有的显示警告消息,有的则完全无动于衷。
但即使编译器允许这种赋值语句,赋给变量intVariable的值也可能是
2,而非四舍五入后的
3。
由于无法保证编译器允许这种赋值语句,所以要避免直接将double值赋给int变量。
常量2.99替换成double类型的变量问题依旧。
大多数编译器对以下赋值语句报错: intintVariable;doubledoubleVariable;doubleVariable=2.00;intVariable=doubleVariable; 虽然2.00不需要四舍五入,但问题依旧存在。
2.00是double而不是int。
如后文所述,可将2.00替换为2赋给doubleVariable,但这依旧无法让编译器正常赋值。
变量intVariable和doubleVariable的类型不同,这才是关键。
即使编译器允许在赋值语句中混用不同类型,但大多数情况下都不应该这样做。
这不利于程序的移植,而且会引起混淆。
例如,如果编译器允许将2.99赋给int变量,该变量获得的将是2而非2.99,这便产生了混淆,因为程序的意思是把2.99赋给变量。
一些特殊情况允许将一种类型的值赋给另一种类型的变量。
将int类型的值赋给double类型的变量是允许的。
例如,以下语句既有效也合乎情理: doubledoubleVariable;doubleVariable=2; 以上语句将doubleVariable变量的值设为2.0。
虽然不建议,但确实可以将int值(如65)保存到char类型的变量中。
另外,还可将字母(如'Z')保存到int类型的变量中。
从多方面考虑,C语言将字符视为小整数值。
遗憾的是,C++从C沿袭了这一点。
之所以选择这样做,是因为char类型的变量占用内存比int类型少。
所以,用char类型的变量进行计算可节省一些内存。
不过,更清晰的方案是在操作整数时使用int类型,操作字符时使用char类型。
一般的规则是,不要将一种类型的值放到另一种类型的变量中——虽然违反这个规则的情况似乎比遵守这个规则的情况多。
即使编译器没有严格贯彻这一规则,你也应该主动遵守。
将一种类型的数据放入另一种类型的变量中可能造成问题。
因为值必须转换成相应类型的值,但转换后的值可能不是你想要的。
bool类型的值可赋给整型(short,int和long)变量,整数也可赋给bool变量。
但这样做不好,应尽量避免。
考虑到知识的全面性,并帮助你阅读其他人写的代码,我打算说具体点:赋给bool类型的变量时,任何非零的整数都将保存为bool值true,值0则保存为bool值false。
反之,将bool值赋给整数变量时,true作为1存储,false则作为0存储。
算术操作符和表达式 C++程序对象程序利用算术操作符合并变量和/或数字。
这些操作符包括+(加)、-(减)、*(乘)和/(除)。
例如,图2.1的程序用操作符*求两个变量值的积,结果放入等号左侧的 第2章C++基础知识51 变量: totalWeight=oneWeight*numberOfBars; 所有算术操作符都可以作用于两个int或两个double,甚至可以一样一个。
但确切的结果值及其类型取决于被合并的两个数字的类型。
两个操作数(也就是两个数字)都是int,用算术操作符合并的结果也是int。
一个(或两个)操作数是double,结果就会变成double。
例如,假定变量baseAmount和increase都是int,则以下表达式的结果也是int: baseAmount+increase 但其中任何一个是double,结果就是double。
将+换为-,*或/,结论一样。
结果类型的重要性可能超乎你的想象。
例如,7.0/2有一个double类型的操作数,即7.0,所以结果是double值3.5。
但7/2的两个操作数都是int,所以结果是int值
3。
即使结果表面上相等,但实际可能还是有区别。
例如,6.0/2有一个double操作数,即6.0,所以结果是double值3.0,它只是一个近似值。
但6/2有两个int操作数,所以结果是int值
3,这是一个精确值。
除法操作符是受参数类型影响最大的操作符。
使用除法操作符时,如果一个或两个操作数是double类型,结果是符合预期的。
但为int类型的两个操作数使用除法操作符,只能获得除法运算结果的整数部分。
也就是说,整数除法丢弃了小数部分。
所以,10/3的结果是3(而不是3.3333…),5/2的结果是2(而不是2.5),11/3的结果是3(而不是3.6666…)。
注意这些数字没有四舍五入,小数部分被直接丢弃,不管它有多大。
将操作符%应用于int类型的操作数,可还原使用/对两个整数进行除法运算时丢失的信息。
应用于int值时,两个操作符/和%将生成执行长除法时获得的两个数(长除法是中学知识)。
例如,17用5除,商3余
2。
/运算得到商,%得到余。
例如,以下语句: cout<<"17dividedby5is"<<(17/5)< 图2.6整数除法 4312 120 12/312%
3 4314 122 14/314%
3 向负int值应用/和%操作符的结果因C++实现而异。
所以,为确保程序的可移植性,只有在确定两个int都非负时,才为它们使用操作符/和%。
算术表达式中可加入合理的空白间距。
可在操作符和圆括号前后插入空格,当然也可以不加。
只要易于阅读,加或不加可自由选择。
52C++入门经典(第10版) 可插入圆括号来指定运算顺序,如以下两个表达式所示: (x+y)*zx+(y*z) 对第一个表达式求值,计算机首先使x和y相加,再将结果乘以z。
对第二个表达式求值,计算机首先使y和z相乘,再将结果加到x上。
尽管数学公式可以使用方括号和其他形式的括号,但C++不允许。
C++只允许在算术表达式中使用圆括号来指定运算顺序。
其他形式的括号有其他用途。
如省略圆括号,计算机将根据优先级规则决定操作符(如+和*)的求值顺序。
这些优先级规则与代数和其他数学课采用的规则相似。
例如,对以下表达式求值时: x+y*z 将先乘后加。
除了一些非常标准的情况(比如一连串的加法,或者在加法运算中嵌入简单乘法),否则最好坚持用圆括号指定执行顺序。
圆括号使表达式更易理解,并避免出错。
附录2给出了完整的C++优先级规则。
视频讲解:PrecedenceandArithmeticOperators 图2.7列出了一些常见的算术表达式和对应的C++表达式。
图2.7算术表达式 数学公式 C++表达式 b*b-4*a*c x*(y+z) 1/(x*x+x+3) (a+b)/(c-d) 陷阱:除法中的整数 两个整数相除结果也是整数。
但如果期望的是小数就会成为问题。
另外,该问题往往不易察觉,导致程序看起来正确,但会产生不正确的输出。
例如,假定园林设计师设计公路景观时按每英里5000美元收费。
已知以英尺为单位的公路长度,使用以下C++语句能轻松计算出应收取费用: totalPrice=5000*(feet/5280.0); 1英里5280英尺,上述语句可行。
假定公路长度15000英尺,以下公式获得总价格: 5000*(15000/5280.0) C++程序按以下顺序获得终值:15000/5280.0结果是2.84。
然后5000和2.84相乘,得到14200.00。
借助于你写的C++程序,可知该工程应收14200美元。
假定feet是int类型,同时忘记包含小数点和后面的
0,赋值语句变为以下形式: totalPrice=5000*(feet/5280); 看起来没错,但会造成严重问题。
使用这种形式的赋值语句,表示要使两个int类型 第2章C++基础知识53 的值相除,所以feet/5280相当于15000/5280,结果是int值2(而不是你希望的2.84)。
所以,赋给totalPrice的值是5000*
2,或者说10000。
忘记小数点,收取的费用就变 成10000美元。
但如前所述,实际应收款是14200美元。
遗漏小数点就蒙受了4200美元 的损失。
注意,totalPrice的类型无论是int还是double,都无法改变这一事实。
损失 发生在向totalPrice赋值之前。
■ √自测题 15.将以下数学公式转换为C++表达式: 3x3x+yxy7 3xyz
2 16.以下几行程序输出什么(假定它们嵌入一个正确的程序,而且所有变量都声明为char类型): a='b';b='c';c=a;cout<可用操作符/和%来实现。
19.给定以下代码段: doublec=20;doublef;f=(9/5)*c+32.0; 它的目的是将摄氏温度(c)换算为华氏温度(f),请回答以下问题。
a.赋给f的值是什么?b.解释实际发生的情况和程序员的本意。
c.重写代码使之符合程序员的本意。
20.以下程序的输出结果是什么(假定它们嵌入一个正确的程序,已将month,day,year和date声明为string类型)? month="03";day="04";year="06";date=month+day+year;cout<常规形式如下: VariableOp=Expression 它等价于: Variable=VariableOp(Expression) 54C++入门经典(第10版) 其中,Op是操作符(比如+,-和*)。
Expression可以是另一个变量、常量或者更复杂的表达式。
下面给出一些例子。
示例count+=2;total-=discount;bonus*=2;time/=rushFactor;change%=100;amount*=t1+t2; 等价形式count=count+2;total=total-discount;bonus=bonus*2;time=time/rushFactor;change=change%100;amount=amount*t1+ cnt2); 2.4简单控制流程 “如果你以为我们是蜡做的人像,那你就应该先付钱,”他说,“你知道,蜡像不是做来给人白看的。
嘿!不是的!” “反过来说,”那个有着“弟”字的小胖子说,“如果你认为我们是活的,你就应该说话。
” ——刘易斯·卡洛尔,《爱丽丝镜中奇遇记》 前面的程序都由一些简单的语句构成。
语句按给定顺序逐行执行。
但更复杂的程序要
求能以某种方式改变语句执行顺序。
语句执行顺序通常称为控制流程或控制流。
本节介绍向程序添加控制流程的两种简单方式。
要讨论一种分支机制,允许程序在两个备选行动中选一个,具体选择哪个由变量值决定。
还要讨论一种循环机制,允许重复一个行动。
一个简单的分支机制 有时需要让程序根据输入从两个备选行动中选一个。
以计算计时员工周薪为例,假定公司薪水制度是每周工作40小时以内,按正常工资计算。
超出40小时算加班,按正常工资1.5倍计算。
员工一周内的工作时间大于或等于40小时,工资计算公式如下: rate*40+1.5*rate*(hours-40)//rate是时薪 但员工工作时间也可能少于40小时。
这种情况下上述公式会算出负值(要体会这一点,可将10代入hours,将1代入rate,并执行计算。
倒霉的员工领到的薪水将为负数。
如工作时间少于40小时,正确薪水计算公式其实是非常简单的,如下所示: rate*hours 要同时支持这两种情况(工作时间大于或等于40小时,或小于40小时),程序必须能在这两个公式之间做出选择。
为计算员工的周薪,程序要采取的行动如下所示: 判断(hours>40)是否为true如果是,执行以下赋值语句: grossPay=rate*40+1.5*rate*(hours-40);如果不是,执行以下赋值语句: grossPay=rate*hours; 第2章C++基础知识55 有一个C++语句专门执行这种分支行动。
if-else语句会在两个备选行动之间选择。
例如,前面讨论的周薪计算可用以下C++语句完成: if(hours>40)grossPay=rate*40+1.5*rate*(hours-40); elsegrossPay=rate*hours; 图2.8用一个完整程序演示了该语句的用法。
图2.8if-else语句 1#include 2usingnamespacestd; 3intmain() 4{
5 inthours;
6 doublegrossPay,rate;
7 cout<<"Enterthehourlyrateofpay:$";
8 cin>>rate;
9 cout<<"Enterthenumberofhoursworked,\n" 10 <<"roundedtoawholenumberofhours:"; 11 cin>>hours; 121314151617181920212223} if(hours>40)grossPay=rate*40+1.5*rate*(hours-40); elsegrossPay=rate*hours; cout.setf(ios::fixed);cout.setf(ios::showpoint);cout.precision
(2);cout<<"Hours="<1 Enterthehourlyrateofpay:$20.00Enterthenumberofhoursworked,roundedtoawholenumberofhours:30Hours=30Hourlypayrate=$20.00Grosspay=$600.00 示范对话
2 Enterthehourlyrateofpay:$10.00Enterthenumberofhoursworked,roundedtoawholenumberofhours:41Hours=41Hourlypayrate=$10.00Grosspay=$415.00 图2.9总结了if-else语句的两种形式。
第一种是最简单的if-else语句,第二种是2.4.4节“复合语句”要讨论的主题。
第一种形式,两个语句可为任何可执行语句。
Boolean_Expression是测试,求值结果要么为true,要么为false。
检查该表达式的值就知道是否满足条件。
之前的if-else语句的Boolean_Expression是: hours>40 56C++入门经典(第10版) 程序到达if-else语句时,实际执行两个内嵌语句之
一。
Boolean_Expression为true(满足条件),执行Yes_Statement。
Boolean_Expression为false(不满足条件),执行No_Statement。
注意,Boolean_Expression必须包含在圆括号内(这是C++if-else语句的语法规则)。
图2.9if-else语句的语法 每个备选行动只有一个语句: 1if(Boolean_Expression)
2 Yes_Statement 3else
4 No_Statement 每个备选行动有一组语句: 5if(Boolean_Expression) 6{78 Yes_Statement_1Yes_Statement_
2 9 ... 10 Yes_Statement_Last 11} 12else 13{1415 No_Statement_1No_Statement_
1 16 ... 17 No_Statement_Last 18} 布尔表达式是求值结果为true或false的表达式。
if-else语句肯定包含一个Boolean_Expression。
最简单的Boolean_Expression由两个表达式(比如数字或变量)构成,它们使用图2.10总结的某个比较操作符进行比较。
注意有的操作符由两个符号构成,例如==,!
=,<=和>=。
注意,必须用双等号==表示相等,用!
=表示不等。
在两个符号构成的操作符中,两个符号之间不能有空格。
执行if-else语句时,首先对要比较的两个表达式进行求值,再用操作符进行比较。
结果为true时,执行第一个语句,否则执行第二个。
图2.10比较操作符 数学符号 中文说法 = 等于 ≠ 不等于 < 小于 ≤ 小于或等于 > 大于 ≥ 大于或等于 C++表示法==!
=<<=>>= C++示例x+7==2*yans!
='n'countlimitage>=21 等价的数学表示 x+7=2yans≠'n'count<m+3time≤limittime>limitage≥21 可用and(逻辑与)操作符(在C++中表示为&&)合并两个比较。
例如,假定x大于
2,而且小于
7,则以下布尔表达式为true(即条件满足): (2 第2章C++基础知识57 “逻辑与”操作符&&可用逻辑与(and)操作符&&将两个简单测试合并成一个更复杂的布尔表达式。
语法(针对使用&&的布尔表达式) (Comparison_1)&&(Comparison_2) 示例(包含在一个if-else语句内) if((score>0)&&(score<10))cout<<"scoreisbetween0and10.\n"; elsecout<<"scoreisnotbetween0and10.\n"; 如果score的值大于
0,同时小于10,就执行第一个cout语句;否则执行第二个。
还可使用or(逻辑或)操作符(在C++中表示为||)来合并两个比较表达式。
例如,假定y小于0或y大于12,则以下表达式为true: (y<0)||(y>12) 用||连接两个比较时,只要其中任何一个为true或者两个都为true(满足任何条件),整个表达式就为true;否则,整个表达式为false。
“逻辑或”操作符||可用逻辑或(or)操作符||将两个简单测试合并为一个更复杂的布尔表达式。
语法(针对使用||的布尔表达式) (Comparison_1)||(Comparison_2) 示例(包含在一个if-else语句内) if((x==1)||(x==y))cout<<"xis1orxequalsy.\n"; elsecout<<"xisneither1norequaltoy.\n"; 如果x等于
1,或者x等于y(或者同时满足这两个条件),就执行第一个cout语句,否则执行第二个。
记住,在if-else语句中使用布尔表达式时,必须用圆括号将布尔表达式封闭起来。
例如,在一个if-else语句中,如if的条件使用了操作符&&,并包含两个比较,就要像下面这样用圆括号封闭if之后的整个比较表达式: if((temperature>=95)&&(humidity>=90))... 注意,总共有两层圆括号,外层的圆括号是必需的,但内层的圆括号(用于封闭不同的比较)则不是必需的。
但由于能使语句结构更清楚,所以通常都会包括它们。
可用求反操作符!
对任何布尔表达式求反。
如希望对一个布尔表达式求反,可以把表达式放入一对圆括号中,再把操作符!
放到它的前面。
例如,!
(x 58C++入门经典(第10版) 由于if-else语句中的布尔表达式必须包含在一对圆括号中,所以在if-else语句中使用求反表达式时,要再用一对圆括号封闭求反表达式。
例如,if-else语句可能这样开始: if(!
(x操作符。
例如,上述if-else语句可更换成以下版本,它是等价的,而且更容易理解: if(x>=y)... 本书很晚的时候才会真正用到!
操作符,届时更详细讨论。
有时希望if-else语句中的一个备选行动不做任何事情。
在C++中,这可以通过省略else部分来实现。
这种形式的语句称为if语句,以区别于if-else语句。
例如,以下两个语句中的第一个语句就是if语句: if(sales>=minimum) //如果实际销售额大于或等于公司规定的最小值, salary=salary+bonus;//就把奖金加上 cout<<"salary=$"<但是,假如sales的值小于minimum,就不执行缩进的赋值语句。
在这种情况下,if语句不会导致任何更改(也就是说,不会有奖金加到基本工资里),程序直接执行cout语句。
陷阱:连续的不等式 不要在程序中使用如下所示的连续不等式: if(x我们将在了解C++语言更多的细节之后,再讨论这个问题的根源。
使用任何比较操作符(而非仅仅是<)来进行一连串的比较时,都会发生同样的问题。
表示连续不等式的正确方式是使用“逻辑与”操作符&&,如下所示: if((x换言之,即使语句在语法上正确,程序能成功编译并运行,不报告任何错误,但结果仍然和希望的不符。
你可能没有意识到一些语句写错了,所以可能导致很严重的问题。
即使发现结果不正确,但绞尽脑汁也想不出症结在哪里。
一个常见的错误是在本该使用==的时候使用了=。
例如像下面这样开头的一个if-else语句: if(x=12) 第2章C++基础知识59 Do_Somethingelse Do_Something_Else 假定要测试x的值是否等于12,所以本意是用==而不是=。
你也许以为编译器能捕捉这个错误,因为对于以下表达式来说: x=12 它不是逻辑表达式,不能表示一个条件是否满足。
相反,它是赋值语句,所以编译器理应报错。
遗憾的是,现实并非如此。
在C++中,表达式x=12和x+12与2+3一样,是一个能返回值的表达式(或者说是具有值的表达式)。
整个赋值表达式的值就是传给等号左侧变量的值。
例如,x=12的值就是12。
从前面对布尔值兼容性的讨论可知,int值可转换成true或false。
由于12是一个非0的值,所以会转换成true。
如果将x=12用作if语句中的布尔表达式,这个布尔表达式将始终为true,所以,程序始终会执行第一个分支(Do_Something)。
这个错误很难发现,因为它看起来是正确的!相反,假如将12放在比较表达式左侧(如下所示): if(12==x)Do_Something elseDo_Something_Else 那么一旦错误地用操作符=来取代上面的操作符==,编译器就会报错。
记住,在操作符==中少写一个=是许多编译器都不能捕捉的常见错误,这个错误很难 发现,而且几乎肯定不会产生你希望的结果。
C++的许多可执行语句可作为几乎任何表达 式使用,其中包括
if-else语句的布尔表达式。
在本该使用布尔表达式的地方使用了赋值 语句,赋值语句会被解释为布尔表达式。
但此时的“测试”结果肯定和你希望的不符。
上 述if-else语句乍一看是对的,也能正常编译和运行,但结果可能出乎预料。
■ 复合语句 经常都要求if-else语句的每个分支执行多个语句。
为此,可将每个分支的语句封闭到一对花括号中,如图2.9第二个语法模板所示,图2.11则给出了一个实际的例子。
花括号内的一组语句统称为复合语句。
在C++中,复合语句被视为单个语句。
凡是能使用单个语句的地方都能换成复合语句(因此,图2.9的第二个语法模板实际是第一个模板的特例)。
图2.11包含两个复合语句,它们嵌入一个if-else语句中。
图2.11在if-else语句中使用复合语句 1if(myScore>yourScore) 2{
3 cout<<"Iwin!
\n";
4 wager=wager+100; 5} 6else 7{
8 cout<<"Iwishtheseweregolfscores.\n";
9 wager=0; 10} 60C++入门经典(第10版) if-else的语法规则要求Yes_Statement和No_Statement分别只能是一个语句。
一个分支要执行若干个语句,就必须将它们放到花括号中,转换成复合语句。
编译器发现if和else之间有两个或多个不在花括号中的语句会报错。
√自测题 21.写一个if-else语句,使其在score变量的值大于100时输出High,在score的值小于等于100时输出Low。
score变量是int类型。
22.假设savings(存款)和expenses(开销)是double类型的变量,而且已经赋值。
写一个if-else语句,如果savings大于等于expenses,就使savings的值减去expenses的值,结果再赋给savings。
然后,将expenses的值设为
0,并输出单词Solvent(有偿还能力)。
但是,如果savings小于expenses,if-else语句就只输出单词Bankrupt(破产),不更改任何变量的值。
23.写一个if-else语句,使其在变量exam(考试成绩)的值大于或等于60,而且变量programsDone的值大于或等于10的条件下,输出单词Passed(通过);否则,if-else语句输出单词Failed(没通过)。
变量exam和programsDone都是int类型。
24.写一个if-else语句,使其在变量temperature(温度)大于或等于100,或者变量pressure(气压)的值大于或等于200,或者同时满足这两个条件的前提下,输出单词Warning(报警);否则,if-else语句输出单词OK(正常)。
变量temperature和pressure都是int类型。
25.假设有以下二次方程式: x2-x-
2 描述它在什么情况下为正(也就是大于0)。
换言之,需要描述要么小于较小根(-1),要么大于较大根(+2)的一系列数字。
写一个C++布尔表达式,使其在方程式为正时求值为true。
26.假设有以下二次方程式: x2-4x+
3 描述它在什么情况下为负。
换言之,需要描述不仅大于较小根(+1),还要小于较大根(+3)的一系列数字。
写一个C++布尔表达式,使其在方程式为负时求值为true。
27.在if-else语句中嵌入的以下cout语句将输出什么?假设已将这些代码嵌入一个完整、正确的程序中。
请解释你的答案。
a.if(0)cout<<"0istrue"; elsecout<<"0isfalse"; cout< 第2章C++基础知识61 简单的循环机制 大多数程序都包含需要多次重复的行动。
以图2.8用于计算员工工资总额的程序为例。
如果公司有100名员工,一个更完善的工资程序将重复这一计算100次。
程序中,用于重复一个或一组语句的那部分称为循环。
C++语言提供了多种方式创建循环。
其中一个称为while语句,或者称为while循环。
为了展示它的用法,首先介绍一个简单的练习程序,再介绍一个更实用的程序。
图2.12的程序含有简单的while语句(以粗体显示)。
花括号{和}之间的部分称为while循环主体,也就是需要重复采取的行动。
花括号内的语句依次执行,执行完一次之后,再从头继续执行,如此重复,直到while循环结束。
在第一个示范对话中,循环主体在循环结束之前,重复执行了三次,所以程序输出了三次Hello。
循环主体的每一次重复都称为循环的一次迭代。
因此,第一个示范对话表明循环进行了三次迭代。
图2.12while循环 1#include 2usingnamespacestd; 3intmain() 4{
5 intcountDown;
6 cout<<"Howmanygreetingsdoyouwant?
";
7 cin>>countDown;
8 while(countDown>0)
9 { 10 cout<<"Hello"; 11 countDown=countDown-1; 12 } 13 cout<\n"; 15 return0; 16} 示范对话
1 Howmanygreetingsdoyouwant?
3HelloHelloHelloThat'sall!
示范对话
2 Howmanygreetingsdoyouwant?
1HelloThat'sall!
示范对话
3 Howmanygreetingsdoyouwant?

0 That'sall!
循环主体执行0次 “while”(当„„时)一词已暗示了while语句的含义。
当圆括号内的布尔表达式满足条件时(求值结果为true),就重复执行循环。
在图2.12中,这意味着只要变量countDown大于
0,就重复执行循环主体。
下面以第一个示范对话为例,研究一下while循环是如何执行的。
用户输入
3,所以cin语句将countDown的值设为
3。
在这种情况下,当程序到 62C++入门经典(第10版) 达while语句时,肯定满足countDown大于0这个条件,所以执行循环主体中的语句。
每次重复循环主体时,都会执行以下两个语句: cout<<"Hello";countDown=countDown-1; 因此,循环主体每次重复都会输出"Hello",同时变量countDown的值递减
1。
计算机重复了三次循环主体后,变量countDown的值递减至
0,圆括号中的布尔表达式不再满足。
所以,重复了三次循环主体后,这个while语句就会终止。
图2.13总结了while语句的语法。
对Boolean_Expression的要求和对if-else语句中的布尔表达式的要求完全一样。
和if-else语句一样,while语句中的布尔表达式也必须用圆括号括起来。
图2.13针对两种情况给出了语法模板:第一种情况是循环主体有多个语句。
第二种情况是循环主体只有一个语句。
注意,只有一个语句时不必使用花括号。
现在着重讨论while语句采取的行动。
执行while语句时,发生的第一件事情是检查单词while之后的布尔表达式。
该表达式的求值结果要么为true,要么为false。
例如: countDown>
0 如果countDown的值为正,则求值结果为true;如果为false,就不采取行动,程序将继续执行while语句之后的下一个语句。
如果比较结果为true,就执行整个循环主体。
在被比较的表达式中,通常至少要有一个包含了即将由循环主体改变的东西,比如图2.12的while语句中的countDown的值。
执行循环主体之后,会再次进行比较。
只要比较结果为true,这个过程就会不断地重复。
循环主体每次迭代后,会再次进行比较,假如结果为true,就再次执行整个循环主体。
一旦比较结果不为true,就结束while循环。
图2.13while语句的语法 while语句执行时,第一件事是检查布尔表达式。
表达式不为true,就永远不执行循环主体,具体可参见图2.12的示范对话
3。
许多时候都要求循环主体执行0次。
例如,假定while循环要读取所有不及格分数,但实际没人不及格,就应该让循环主体执行0次。
一个while循环可能执行0次循环主体,这是很正常的情况。
但是,如果要求循环主体在任何情况下都至少执行一次,就应该使用do-while循环。
do-while语句与while语句相似,只是它的循环主体至少执行一次。
do-while语句的语法请参见图2.14。
图2.15是使用了do-while循环的示范程序。
do-while循环的第一件事情就是执行循环主体语句。
循环主体第一次迭代之后,do-while的行为就和while一样了。
换言之, 第2章C++基础知识63 就是检查布尔表达式,结果为true就再次执行循环主体,再次检查布尔表达式,如此反复。
图2.14do-while语句的语法 图2.15do-while循环 1#include 2usingnamespacestd; 3intmain() 4{
5 charans; 678910111213 14 1516} do{ coutcout cin}while <<"Hello\n";<<"Doyouwantanothergreeting?
\n"<<"Pressyforyes,nforno,\n"<<"andthenpressreturn:";>>ans;(ans=='y'||ans=='Y'); cout<<"Good-Bye\n"; return0; 示范对话 HelloDoyouwantanothergreeting?
Pressyforyes,nforno,andthenpressreturn:yHelloDoyouwantanothergreeting?
Pressyforyes,nforno,andthenpressreturn:YHelloDoyouwantanothergreeting?
Pressyforyes,nforno,andthenpressreturn:nGood-Bye 递增操作符和递减操作符 2.3节讨论了二元操作符。
二元操作符有两个操作数。
一元操作符则只有一个。
之前用过两个一元操作符,即+和-,它们在+7和-7这样的表达式中使用。
C++语言还有另外两个很常用的一元操作符,即++和--。
操作符++称为递增操作符,操作符--称为递减操作符。
它们通常与int类型的变量一起使用。
假定n是int类型的变量,n++使n递增1,n--使n递减
1。
所以,n++和n--(后跟一个分号)是可执行语句。
例如以下语句: 64C++入门经典(第10版) intn=1,m=7;n++;cout<<"Thevalueofnischangedto"<递增和递减语句常在循环中使用。
例如,图2.12的while循环中使用了以下语句: countDown=countDown-1; 但大多数有经验的C++程序员都会选择使用递减操作符。
所以整个while循环可这样修改: while(countDown>0){ cout<<"Hello";countDown--;} 编程实例信用卡余额 假定有一张信用卡,卡上已产生应还金额50美元,银行按2%月利率收费。
假定一直不还款,多少个月之后,这张卡的应还金额会超过100美元?解决这个问题的一个办法是查看每月账单,统计在应还金额达到或超过100美元之前,总共会经历多少个月。
但更好的办法是用程序计算每月应还金额,而不必等着银行寄账单。
通过这种方式,不需要漫长的等待(也不会影响自己的信用评级),就能迅速得到答案。
一个月后,卡的应还金额是50美元加50美元的2%,也就是51美元。
两个月后,卡的应还金额是51美元加51美元的2%,也就是52.02美元。
三个月之后,卡的应还金额是52.02美元加52.02美元的2%,依此类推。
总之,每月应还金额都会增加2%。
该程序将应还金额保存到名为balance的变量中对其进行跟踪。
每月对balance变量值的修改可以像下面这样进行: balance=balance+0.02*balance; 重复这个行动,直到balance的值达到(或超过)100美元,并对重复次数进行计数,就知道多少月后应还金额达到100美元。
为此,需要用另一个变量对balance的修改次数进行计数。
假定新变量名称是count。
while循环中最终的主体将包含以下语句: balance=balance+0.02*balance;count++; 为了使循环正确执行,必须在循环执行之前将恰当的值赋给变量balance和count。
本例在声明变量的同时初始化。
完整程序参见图2.16。
第2章C++基础知识65 图2.16信用卡程序 1#include 2usingnamespacestd; 3intmain() 4{
5 doublebalance=50.00;
6 intcount=0;
7 cout<<"Thisprogramtellsyouhowlongittakes\n"
8 <<"toumulateadebtof$100,startingwith\n"
9 <<"aninitialbalanceof$50owed.\n" 10 <<"Theinterestrateis2%permonth.\n"; 1112131415 1617181920 2122}23 while(balance<100.00){ balance=balance+0.02*balance;count++;} cout<<"After"<(2);cout<<"yourbalanceduewillbe$"<布尔表达式通常包含一个将由循环主体更改的变量。
变量应不断更改,最终使布尔表达式求值为false,从而终止循环。
但假如不小心让布尔表达式始终为true,循环就会一直运行。
这种循环称为无限循环。
首先描述一个能终止的循环。
以下C++代码输出小于12的所有正偶数。
也就是说,它将逐行输出数字2,4,6,8和10,然后循环终止: x=2;while(x!
=12){ cout<2,直到变成12。
此时,单词while之后的布尔表达式不再为true,循环结束。
现在假设要输出小于12的奇数,而不是偶数。
你可能以为只需这样修改初始化语句: x=1; 66C++入门经典(第10版) 但这是错误的,它会导致无限循环。
因为x的值会从11变成13,永远不等于12,所以循环永远不会终止。
用==或!
=检查一个数来终止循环,很容易造成无限循环问题。
处理数字时,更安全的做法始终是测试它是否超过了一个值。
例如,将前面while循环的第一行改为以下语句,就可将x初始化为任意数字,循环始终都能正常终止: while(x<12) 无限循环的程序不能自动停止,除非强行终止。
初学编程的读者可能写出含有无限循 环的程序,所以最好学会怎样强行终止程序。
强行终止程序的方法因系统而异。
在很多系 统上,按Control+C(按Ctrl键的同时按C键)就可以终止程序。
■ √自测题 28.以下代码的输出是什么(假定它们已嵌入一个正确的程序,而且x已声明为int类型)? x=10;while(x>{ cout<替换为<会输出什么? 30.以下代码的输出是什么(假定它们已嵌入一个正确的程序,而且x已声明为int类型)? x=10;do{ cout<0); 31.以下代码的输出是什么(假定它们已嵌入一个正确的程序,而且x已声明为int类型)? x=-42;do{ cout<0); 32.while语句和do-while语句有何重要区别? 33.以下代码的输出是什么(假定它们已嵌入一个正确的程序,而且x已声明为int类型)? x=10;while(x>{ cout<该程序不执行别的任务。
第2章C++基础知识67 2.5程序风格 在非常重要的事情上,最要紧的并非真诚,而是格调。
① ——奥斯卡·王尔德,《不可儿戏》 我们的示范程序中,所有变量名都准确表达了它们的用途。
示范程序在编排上采用了一种特定的格式。
例如,声明和语句的缩进量是相同的。
这些风格不仅仅是为了美观。
风格好的程序更容易阅读,更容易纠正,也更容易修改。
缩进 程序应合理编排,使原本就是一个整体的各元素能组合到一起。
一种方法是在逻辑上独立的各个部分之间插入空行。
合理的缩进也有助于澄清程序结构。
包含在一个语句内部的其他语句应该缩进。
特别是,if-else语句、while循环和do-while循环应该缩进。
缩进可采用示范程序的方式,也可采用其他类似的方式。
花括号{}用于确定程序结构中的一个较大的部分。
像示范程序中那样,使每个花括号都单独占一行,以便定位一对匹配的花括号。
注意,我们有意缩进了一些花括号。
如果一对花括号要嵌入另一对中,嵌入的那一对花括号的缩进量要大于外面那一对,具体可参见图2.16。
while循环主体的花括号缩进量应该大于程序main部分的花括号的缩进量。
至于在何处放置花括号,至少有两种理论。
一种是像本书那样,每个花括号都单独占一行。
这种形式更容易阅读。
第二种是起始花括号不单独占一行。
如果小心使用,第二种方法将更高效,而且更省空间。
采用某种风格时,关键在于澄清程序结构。
最终采用什么风格是因人而异的,你应该在自己的所有程序中坚持自己既定的风格。
注释 为使程序容易理解,应在程序的关键位置添加一些解释性批注。
这些批注称为注释。
C++和其他大多数编程语言一样都允许添加程序注释。
在C++中,符号//指出一条注释开始。
符号//与行末之间的所有文本都是注释文本。
编译器会忽略//之后这一行的所有内容。
如果一条注释需要占据多行,就在每行注释之前添加符号//。
符号//由两个连续的斜杠构成,之间无空格。
本书代码没有使用特殊格式,但在某些代码编辑器中,会使用和其他程序文本不同的颜色显示注释。
在C++程序中,还有另一种方式插入注释。
符号/*与*/之间的所有内容都会被视为注释,并被编译器忽略。
/*到*/之间的注释可自由跨越多行。
这样一来,就不需要像//注释那样,在每一行上都要添加一个额外的//。
如下所示: /*这是一条跨越三行的注释。
注意第二行没有任何形式的注释符号.*/ ①格调、风格、样式在英语里面都是Style。
——译注 68C++入门经典(第10版) 在程序中,但凡允许插入空格或换行符的位置,都允许插入/**/风格的注释。
但不要把它插入不利于阅读的位置,也不要插入会干扰程序布局的位置。
注释通常只应放在行末,或单独占一行。
至于哪种注释风格更好,人们的看法不
一。
但是,只要使用得当,任何一种注释都能取得理想的效果。
本书统一采用//注释。
很难说程序中应该包含多少注释。
唯一正确的答案是“够用就好”,但这对刚入门的程序员来说意义不大。
只有积累一定经验之后,才能更好地把握添加注释的时机。
一般在重要和不容易理解的地方添加注释。
但注释太多有“喧宾夺主”之嫌。
每行都有注释的程序使人难以看清程序的结构。
例如,以下注释意义不大,不如不用: distance=speed*time;//计算旅行的距离 注意图2.17的程序开头给出的注释。
所有程序都应该以类似的注释开头。
它给出了程序的所有基本信息:程序包含在哪个文件中、谁写的程序、如何联系作者、程序有何用途、程序的最新修改日期以及其他需要传达的信息,比如作业编号(如果该程序是课堂作业的话)。
注释的具体内容要视情况而定。
我们不打算在本书的其他程序中添加如此长的注释。
但在你的程序中,应坚持在程序开头包含这样的注释。
图2.17注释和命名常量 1//文件名:health.cpp(你的程序可能需要一个不同于cpp的扩展名) 2//作者:<在此填写你的姓名> 3//电子邮件:you@yourmachine.bla.bla4//题号:
2 程序坚持以这种注释开头 5//说明:判断用户是否生病的程序 6//上一次修改:2017年9月23日
7 8#include 9usingnamespacestd; 10intmain() 11{ 12 constdoubleNORMAL=98.6;//正常体温(华氏度) 13 doubletemperature; 14 15 cout<<"Enteryourtemperature:"; 16 cin>>temperature; 17 18 if(temperature>NORMAL) 19 { 20 cout<<"Youhaveafever.\n";//你发烧了 21 cout<<"Drinklotsofliquidsandgettobed.\n";//多喝水,卧床休息 22 } 23 else 24 { 25 cout<<"Youdon'thaveafever.\n";//你没有发烧 26 cout<<"Gostudy.\n";//去上学 27 } 28 29 return0; 30} 示范对话 Enteryourtemperature:98.6Youdon'thaveafever.Gostudy. 第2章C++基础知识69 为常量命名 计算机程序的数字存在两个问题。
第一是不好记。
例如,数字10在程序中出现时,不能就其含义传达任何有意义的信息。
例如在银行程序中,10既可能是分行数量,也可能是总行出纳窗口数量。
理解程序需知道每个常量的含义。
第二是程序更改部分数字时容易出错。
假定数字10在上述银行程序中出现了12次,其中4次代表分行数,另外8次代表总行出纳窗口数。
一旦银行开设新的分行,并需要更新程序,有的10可能需要变成11,有的根本不能改动。
为了避免这些问题,一个办法是为每个数字命名,在程序中使用名称而不是数字本身。
例如,可在银行程序中包含两个常量,分别命名为BRANCH_COUNT(分行数)和WINDOW_COUNT(窗口数)。
两个常量的值可能都为10,但在开设新分行时,只需更改BRANCH_COUNT的定义就可以了。
如何命名C++程序中的数字呢?一个办法是将变量初始化为那个数字,示例如下: intBRANCH_COUNT=10;intWINDOW_COUNT=10; 但是以这种方式命名数字常量也有问题:你可能会不小心更改上述变量的值。
C++提供了一种方式来标记初始化好的变量,使其不能更改。
程序试图更改就会出错。
要标记一个不能更改的变量,请在变量声明之前添加单词const(constant的缩写)。
例如: constintBRANCH_COUNT=10;constintWINDOW_COUNT=10; 如果变量为同一类型,上述两行可合并为一个声明,如下所示: constintBRANCH_COUNT=10,WINDOW_COUNT=10; 但大多数程序员都认为,每个名称定义单独占一行显得更清楚。
const这个词通常称为修饰符,因其修饰(限制)了被声明的变量。
使用const修饰符声明的变量称为声明常量或命名常量(namedconstant)。
C++语言不要求声明常量的名称全部大写,但这已成了C++程序员约定俗成的标准。
一旦像这样命名了数字,在需要使用该数字的任何地方,都可以使用它的名称。
名称和数字本身具有完全相同的含义。
更改命名常量只需更改const变量声明的初始值。
例如,要将BRANCH_COUNT的值从10改为11,只需修改BRANCH_COUNT声明的初始值10。
尽管可以在程序中使用未命名的数字常量,但尽量少用。
通常,只有已知的、容易识别的而且不会改变的量(比如“1米等于100厘米”中的100)才可以使用未命名的数字常量。
但其他所有数字常量都应该像刚才描述的那样指定名称。
这会使程序更容易阅读和修改。
图2.17用一个简单程序展示了如何使用const修饰符。
用修饰符const命名常量在声明中初始化变量时,可以标记变量,使程序不能更改该变量的值(使之成为常量)。
为此,可在声明的开始处添加修饰符const,如下所示:语法 constType_NameVariable_Name=Constant; 示例 constintMAX_TRIES=3;constdoublePI=3.14159265; 70C++入门经典(第10版) √自测题 35.以下if-else语句能正确编译和运行。
但风格和本章其他程序不一致。
修改它使风格(缩进和换行)一致:if(x<0){x=7;cout<<"xisnowpositive.";}else{x=-7;cout<<"xisnownegative.";} 36.以下两行语句的输出是什么(假定已把它们嵌入一个完整和正确的程序)?//cout<<"Hellofrom";cout<<"Self-TestExercise"; 37.写完整的C++程序,要求用户输入加仑数(gallon),再输出等价的公升数(liter)。
1加仑等于3.78533公升。
请使用一个声明常量。
这只是练习题,不需要在程序中添加任何注释。
第2章C++基础知识71 小结 为变量使用有意义的名称。
务必将变量声明为正确的数据类型。
变量使用前必须初始化。
可在声明时初始化,也可在使用前用赋值语句初始化。
在算术表达式中合理使用圆括号,清楚指定运算顺序。
每次要求用户从键盘输入数据的时候都显示提示,并始终回显输入。
if-else语句允许程序在两个备选行动中选择一个。
if语句允许程序决定是否 执行一个特定的行动。
do-while语句至少执行一次循环主体。
而while循环有可能一次都不执行。
程序中,几乎所有数字常量都应被赋予有意义的名称,并在程序中使用名称代 替数字。
在变量声明中添加修饰符const来实现。
使用与本书示范程序类似的缩进、间距和换行风格。
插入注释来解释一个程序的重要小节或者任何不清楚的地方。
72C++入门经典(第10版)C++入门经典(第10版) 自测题答案 1.intfeet=0,inches=0;intfeet
(0),inches
(0); 2.intcount=0;doubledistance=1.5; 也可以使用: intcount
(0);doubledistance(1.5); 3.sum=n1+n2; 4.length=length+8.3; 5.product=product*n;
6.这种程序的实际输出取决于系统和系统的使用历史。
#include usingnamespacestd;intmain(){intfirst,second,third,fourth,fifth;cout<7.没有标准答案,以下答案仅供参考:a.speedb.payRatec.highest或maxScore 8.cout<<"Theanswertothequestionof\n" <<"Life,theUniverse,andEverythingis42.\n"; 9.cout<<"Enterawholenumberandpressreturn:"; cin>>theNumber; 10.cout.setf(ios::fixed); cout.setf(ios::showpoint);cout.precision
(3); 11.#include usingnamespacestd;intmain(){ cout<<"Helloworld\n";return0;} 12.#include usingnamespacestd; intmain(){intn1,n2,sum;

标签: #怎么回事 #文件类型 #c53怎么算 #文件 #文件夹 #角度 #clio #文件夹