第五章(中文)_第1页
第五章(中文)_第2页
第五章(中文)_第3页
第五章(中文)_第4页
第五章(中文)_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

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

文档简介

1、第五章 条件、逻辑表达式和选择控制结构目标: 能够构造一个简单的逻辑(布尔)表达式来求一个给定条件的值。 能够构造一个复杂的逻辑表达式来求一个给定条件的值。 能够构造一条If-Then-Else语句来完成一个指定的工作。 能够构造一条If-Then语句来完成一个指定的工作。 能够构造一组If嵌套语句来完成一个指定的工作。 能够为一个模型确定前提条件和事后条件并使用它们执行一个算法过程。 能够跟踪一个C+程序的执行。 能够测试和调试一个C+ 程序。 5.1 控制流程程序中语句执行的顺序称为控制流程。控制流程通常是顺序执行的(见图5-1),当我们希望控制流程是非顺序的时候,我们使用控制结构,将控制

2、流程转向指定的语句,而不是物理位置顺序接着的语句。控制结构:用来交换正常顺序控制流的语句选择当我们想要计算机选择两者之一的活动时,我们使用一个选择(或分支)控制结构,我们做一个判断,声称是真还是假,如果判断是真的,计算机执行一条语句,如果为假,计算机执行是一条语句(见图5-2)。 5.2 条件和逻辑表达式在C+中为了提出一个问题,我们使用一个判断语句。计算机求取判断语句的值,依靠某种内部条件来检查它,看它是真还是假。布尔数据类型在C+中,布尔数据类型是仅由两个值组成的标准类型,两个值是常量true和false。保留字bool是Bolean的缩写。布尔数据在程序中用来测试条件,以便计算机能够做出

3、判决(具有一个选择控制结构)。我们声明布尔类型变量与我们声明其它变量和方法一样,即写数据类型名,然而是标识符.。bool dataOK; /如果输入数据有效为真bool done ; /如果过程被做了为真bool taxable ; /如果项目有销售税为真每个bool类型变量可以包含两个值:true或fales之一,理解右边开始的true和fales不是变量名,也不是字符串是重要的,它们是C+中特殊的常量,事实上是保留字。逻辑表达式在C+中,判断采取逻辑表达式的形式。一个辑表达式由逻辑值和操作组成,每个逻辑表达式有两个值:true或false之一,这里是一些逻辑表达式的例子. 布尔变量或常量

4、一个表达式接着一个关系操作符再接着一个表达式 一个逻辑表达式接着一个逻辑操作符再接一个逻辑表达式让我们详细看看每一种形式:布尔变量和常量像我们已看到的一样,一个布尔变量是一个声明为bool类型的变量,它可包含一个true值也可包含一个false值,例如,如果dataOK是一个布尔变量,那么,dataOK = true;是一个有效的赋值语句。关系运算符另一个赋一个值给布尔变量的方法是:用一个关系运算符设置这个值等于两个表达式比较的结果,关系运算符测试两个表达式值之间的关系。让我们看一个例子,在下列程序段中,lessThan是一个布尔变量,i和j 是int变量:cin i j ;lessThan

5、= ( i j ); / 如果i 大于= 大于或等于 x y = xx ! = y x y x = y如果x是字符M并且y是R,表达式的结果仍是true ,因为用于字符中的关系运算符, 意思是“M在字符设置顺序对照表中在R之前”。例如,广泛使用的ASCll字符设置,所有大写字母是以字母顺序排列的,小写字母也是一样,但是,所有大写字母在小写字母之前,所以MR 和 mr的值是true,但是m = float(someInt)如果你比较一个布尔值和一个数字值(可能会出错),false值是暂时强制成数0,true强制成数1,因此,如果boolVar是一个bool变量,表达式boolVar 5产生tru

6、e ,因为0和1都小于5。例如,比较0 9 和 0 9是合适的,但是0 9产生一个隐含类型强制并且结果可能不是你所期望的。 我们不仅可以使用关系运算符比较变量或常量,而且可以比较算术表达式的值。在下列表中,我们取不同的x和y的值,将x加3的结果与y乘10的结果比较。注意:容易混淆赋值运算符(=)与关系运算符= = ,在程序中,两个运算符有非常不同的效果。串比较回忆第4章,string是一个类用户自定义的类型,你用这个类型声明变量,这个变量更常称为对象。包含在每个string对象内的是一个字符串,string类被设计成可以使用关系运算符来比较这些串,按照句法规则,关系运算符的操作数可以是两个st

7、ring对象,像在myString = ”Johnson”可是,操作数不可以都是C串。串的比较是遵循计算机字符设置(如ASCII)的排列顺序来进行的。当计算机测试两个字符间的关系时,在每个串中从第一个字符开始,按照排列顺序比较它们,如果它们相同,重复比较下一个字符,一个字符一个字符的测试下去,直至找到一个不匹配的字符或最后一个字符比较完也是相等为止。如果它们所有字符老师相等,那么两个串是相等的。如果有一个不匹配字符被找到,那么字符排列在前的串是更小的串。例如,给出语句string word1 ;string word2 ;word1 = ”Tremendous” ;word2 = ”Small

8、” ;在下列表中的关系表达式有指定的值。如果有两个不同长度的串比较,相等比较是一直到较短的串的末尾,然后,较短的串小于较长的串,例如,如果word2包含”small”,表达式word2 90 & midtemScore 70AND操作(&)需要两个关系式都是真,总的结果才是真,如果两个关系式有一个为假,总的结果为假。OR操作(|)取两个逻辑表达式并把它们结合在一起,如果两者中有一个为真,结果为真,两个值必须都为假,结果才会为假。现在我们可决定是期中成绩为A还是期末成绩为A,如果期中成绩或者期末成绩等于A,判断式为真,在C+中,我们写表达式像这样:MidtermGrade = = A | fin

9、alGrade = = A&和|运算符是双目(两个操作数)运算符。NOT运算符(!)是单目(一个操作数)运算符,它对一个逻辑表达式操作并给出它的相反值作为结果。如果(grade = =A)是假,那么!(grade = =A)是真。NOT给我们一种判断意思相反的方便的方法,例如,!(hours 40) 等价于 hours = 18 & district = = 23 )赋一个值给布尔变量isElector,我们可以使用两个中间布尔变量,isVoter和isConstituent :isVoter = ( age = 18 ) ;isConsticuent = ( district = = 23)

10、 ;isElector = isVoter & isConstituent ;下面两个表格总结了一对逻辑表达式应用&和 | 的结果(这里x 和y用布尔变量表示)。下面表格总结了对一个逻辑表达式应用!运算符的结果(x表示布尔变量)在技术上,C+运算符!,&和|不需要有逻辑表达式作为操作数。它们的操作数可以具有任何简单数据类型甚至浮点类型,如果一个操作数不具有bool类型,它的值暂时强制成bool类型如下:0 值强制成false ,并且任何非零值强制成true。贯穿本书,我们将逻辑运算符仅应用于逻辑表达式,而不是用于应用算术表达式。短路径(条件)求值:一个逻辑表达式的求值是从左到右,一旦最终真实值

11、能被决定求值就停止。考虑逻辑表达式i =1 & j 2C+采用短路径(或有条件的)求逻辑表达式的值。求值过程从左到右,计算机有可能就停止求子表达式的值即,只要它一知道整个表达式真实值时就停止子表达式求值,如果计算机不检查所有子表达式,它如何能知道,一个过长的逻辑表达式是产生true还是false?让我们首先看看AND操作。如果AND的两个操作数是true,AND操作产生true值。在上面表达式中,假如i的值是95,第1个子表达式产生false,所以计算机甚至不必看第2个子表达式,计算机就停止求值并产生最后false结果。具有或OR的操作,从左到右求值,只要一找到产生true的子表达式,求值就停

12、止,记住,OR操作数中的一个或两个为true,OR产生一个true的结果。给出这个表达式c = d | e = f如果第1个子表达式是true,求值停止并且整个表达式的结果是ture。计算机不浪费时间对第2个子表达式的不必要求值。运算符的优先权在第3章中,我们讨论了求取算术表达式的优先权规则。C+也给出了关系和逻辑运算符的优先权规则,这里是一个列表,显示了算术,关系,逻辑运算符的优先权顺序(赋值运算符也给出了)列表中同一行的运算符优先权相同,如果一个表达式包含几个具有相同优先权运算符,大部分运算符组(或伙伴)从左到右求值,例如,表达式a / b * c意味着( a / b )* c ,不是 a

13、 / (b * c),可是,单目运算符组(!,单目+,单)是从右到左,虽然你从没有机会使用这个表达式:! bad Data这意味着!(!badData)而不是意味着(!)badData ,附录B, “运算符的优先权”,列出了C+中所有运算符的优先权次序。 关系运算符与浮点类型不要用等于号来比较实数:当执行实数计数时,由于在最右边小数位置中的小误差,两个实数值几乎不能确切地相等,例如,考虑下面使用两个名为oneThird和x的实型变量:oneThird =1.0 /3.0 ;x = oneThird + oneThird + oneThird ;我们会认为x包含的值为1.0,但是它可能不是,第一

14、条赋值语言存储一个1/3的近似值到oneThird,也许是0. 。第2 条语句存储一个像0.这样的值到x中,如果我们现在要计算机比较x和1.0,比较结果产生false。比较实数相等,我们采用近似相等测试来取代,为了这样做,我们计算两个数之间差值,测试看看结果是否小于某些允许的最大差值,例如,我们常使用像这样的比较。fabs( r s) 0.00001这里fabs是 C+标准库中实数绝对值的函数 。表达式fabs (r s)计算两个float变量r和s差值的绝对值。如果差值小于0.00001,两个数足够接近称它们相等。常见错误逻辑表达式中许多错误在于英语中我们倾向采取的简化操作,我们也许查询期中

15、成绩是不是A或者期末成绩是不是A但是如果我们在C+中直接写为midtermGrade | |finalGrade = = A我们得到一个错误的结果,因为或运算符 | 连接了一个字符值(midtermGrade)和一个逻辑表达式(finalGrade = =A),或 | |的两个操作数应该是逻辑表达式,所以我们必须写为midtermGrade = =A | | finalGrade = =A类似地,判断i是否等于3还是4,不能写为i = =3 | 4而必须写为i = =3 | i = = 4数学中使用的标记12 y 24意思是“y是在12与24之间”,但是直接将这个标记转换为C+就会有一个不同的

16、效果。首先,关系式12 y 被求值,给出结果true 或false 然后,计算机把这个结果强制成 1和0都小于24 ,结果总是 true,正确转换的C+是12 y & y 24 5.3 If 语句现在我们已看到了如何写逻辑表达式,让我们使用它们来改变程序中正常的控制流。If语句是基本的控制结构,允许在控制流中产生分支。用它,我们可以提出一个问题并且选择一个行为方向:If某条件存在,那么完成一项行为,else否则执行一项不同的行为。 If ThenElse 形式在C+中,If语句以两种形式出现,IfElse形式和If形式。让我们看看第1种IFElse形式,这里是它的语法模板。圆括号中的表达式可以

17、是任何简单数据类型,几乎没有例外,表达式将是一个逻辑(布尔)表达式,如果不是,它的值隐含强制成bool类型,在执行时,计算机求表达式的值,如果值是true,计算机执行语句1A,如果表达式的值为false,语句1B被执行,语句1A常被称为then-clause ,语句1B被称为 else-clause, 图5-3说明了If Then-Else的控制流程,在图中,语句2是程序中整个If语句后面的下一条语句。注意,一个C+ If 语句使用保留字if 和else而不包含字then,我们仍使用术语If Then Else ,因为它与我们用英语说的事“If(如果)某事为真,then(那么)做这个,else

18、(否则)做那个”相符合。下面代码段显示了在程序中如何写If语句。观察then从句和else从句的缩排形式,这使得语句更容易阅读,注意下列If语句的位置。if (hours = 40.0)Pay = rate * hours ;else Pay = rate * (40.0+(hours-40.0)*1.5) ;cout pay ;按照计算机的指令,上面代码段说,“如果hours 是小于或等于40.0,计算常规薪水,然后继续执行输出语句;但是如果hours 是大于40.0,计算常规薪水和超时薪水,然后继续执行输出语句。”作为另一个If-Then-Else的例子,假如我们想决定一个string变量

19、中字母A第一次出现所处的位置,回想第3章,串类有一个成员函数名为find,这个函数返回所找到项目的位置(如果项目没有找到,返回名字常量 string : : npos),下列代码输出搜索的结果。string myString;string:size_type pos;.pos = myString.find(A) ;if (pos = string:npos)cout No A was found endl;elsecout An A was found in position pos endl;按照模板,在If语句的末尾没有分号。在上面两个程序段中工人的薪水和串搜索例子似乎在每个If语句末尾

20、都有一个分号。可是,在这些例子中,这个分号属于else从句;赋值语句以分号结束,输出语句也以分号结束。If语句在末尾没有自己的分号。块(复合语句)在一个表达式中,检查避免被零除,假如当除数等于零时,我们想要做两件事:打印一个错误信息。并设置名为result的变量等于一个像9999这样的特殊值,在同一分支中,我们会需要两条语句,但是语法模板似乎限制我们一条语句。我们真正想做的事是,将else从句转成一系列的语句,这是容易的、记住第2章中编译器处理的块。.就像单条语句一样,如果在一个If语句的分支中,你用一对花括号括起语句序列,语句序列变成为单个块 例如:if (divisor != 0)resu

21、lt = dividend / divisor ;elsecout Division by zero is not allowed. endl ;result = 9999;如果divisor的值是0 ,在继续If 语句后面的任何语句之前,计算机打印错误信息中设置result变量的值为 9999.块可以用在 If Then else 两个分支语句中,例如:if (divisor != 0)result = dividend / divisor;cout Division performed. endl ; elsecout Division by zero is not allowed. en

22、dl ;result = 9999: 当你在一个If语句中使用块,有一个C+语法规则要记住:在块的右花括弧后面,决不能使用分号,分号用来中止简单语句,例如赋值语句,输入语句,和输出语句。在上面例中,在花括号后没有分号,右花括弧发出每个块结束的信息。If- Then 形式有时,你运行到一种情况,在这种情况下,你想说:“如果某一条件存在,那么完成某些活动;其它情况,不做任何事情”,换句话说,如果某一条件不满足,你想要计算机跳过一系列指令。你可以让else分支空着来做到这点,即仅使用空语句:if ( a b )c = 20 ;else ;然而,最好你可以简单地去掉else部分。导致的语句是:If语句

23、的If-Then形式。这是它的模板If 语句 ( if then 形式)If (表达式)语句这里是 If Then的一个例子,注意下列If Then语句的缩排形式和位置。If ( age 18 )cout “Not an eligible” ;cout “voter .” endl ;这条语句意味着,如果age小于18,首先打印 “Not an eligible” ,然后打印机“voter.”。如果age 不小于18。跳过第一条输出语句并直接打印“voter”。像在If Then-Else 中一样,If Then中的分支可以是一个块,例如,让我们说,你正在写一个计算所得税的程序。有关税形式其中

24、之一解释为“ 从 line 17 减去 line 23。并且得到结果在line 24中;如果结果小于零,结果为0,并且显示 check box 24 A”。你可以在C+中使用一个If-Then来做到这点。result = line 17 line 23 ;if ( result 0.0 )cout ”check box 24A “ endl ;result= 0.0 ;line 24 = result ;这个代码确切地做了它应做的税收形式,它计算了从line 17 减去 line 23结果,然后它查看结果result是否小于0,如果是小于0,这个代码段打印一条告诉用户检查24A盒的信息,然后设

25、置结果result为0,最后,计算结果(或0,如果结果小于0的话)存储到名为 line 24的变量中。如果我们去掉上面代码段中的左和右花括弧会发生什么情况?让我们看看:result = line 17 line23 /不正确的版本if ( result 0.0)cout ”check box 24 A” n ; if (n =3) / 错误cout n equals 3;elsecout n doesnt equal 3;不管n输入什么值,这个代码段总是打印n euqal 3这个错误原因是:我们在if 测试中使用了错误的操作符,表达式 n= 3不是一个逻辑表达式;它被称为赋值表达式,一个赋值表

26、达式有一个值(上面的表达式的值是3)和一个副效应(存储3到n中),在我们例子中的if 语句,计算机找到被测表达式的值是3,由于3是一个非零值,因而被强制为true,不管n的值是什么then从句被执行。目前的错误是,赋值表达式的副效应是存储3到n中,损坏了那里所要做的判断。 5.4 If语句的嵌套在If语句中,语句是什么没有限制,因此,一个If语句内有If语句可以的,事实上,一个If语句在一个If语句中然后再在一个If语句中是合法的。这里仅有的限制是,人们不能允许一个太多包含的结构,由于可读性是好程序的标志之一。当我们设置一个If语句在另一个If语句内时,我们正建立一个嵌套控制结构,控制结构嵌套

27、非常像嵌在一起的钵,较小的钵嵌在较大的钵内,这里是一个例子以伪代码写:通常,任何包含多分支 (多于两个可选择的活动情况) 问题,可以使用嵌套If语句编码,例如,给出月份数字,打印出月份的名字,我们可以使用一系列If语句(非嵌套):if ( month =1 )cout ”January ” ;if ( month =2 )cout ” February ” ;if ( month =3 )cout ” march ” ;if ( month =12 )cout ” December ” ; 但是等价嵌套If结构if ( month =1)cout ”January ” ;else if (mo

28、nth =2) /嵌套Ifcout ” February ” ;else if ( month = 3 ) /嵌套Ifcout ” march” ;else if ( month = 4 ) /嵌套If是更有效的,因为它使得语句有更少的比较,第1种版本独立的If语句序列总是测试每个条件(所有12个数字),即使第一个比较就满足,也是如此。相反,嵌套If语句的解决方法是在一个选项被选择后,跳过所有剩下的比较。 在后一个例子中,注意then和else从句的缩排,是怎样使语句连续右移。我们能够取代地使用具有深度嵌套的If Then-Else语句的一种指定的缩排风格来指示复杂结构,这种复杂结构仅选择一套

29、选项中的一个,这种通常的多分支方法被称为If Then- Else-If 控制结构if ( month =1 )cout ”January ” ;else if ( month =2 ) /嵌套Ifcout ”February ” ;else if ( month = 3 ) /嵌套Ifcout ” march ” ;else if ( month = 4 ) /嵌套If:elsecout “ December ” ;这种风格防止进行连续右移的缩排,但是,更重要的是,它视觉上传达了这样的思想,我们正使用基于变量month的12种方法的分支。注意If语句序列和嵌套If之间的不同是重要的:多于一个

30、的选项可以采取序列If语句,而嵌套If只能选择一个。为了看看这点为什么是重要的,考虑分析填写调查表,有些问题像一系列If语句,要求你在提供给你的一张表(例如所有你的爱好表)中,圈出所有项目。另一些问题要求你在一个表(例如,你的年龄组)中只圈出一个项目,因而像一个嵌套If语句结构,两种问题都会出现在编程问题中,为了能够识别哪种类型的问题被要求,允许你立即选择适合的控制结构。另一种特殊的有帮助的嵌套If的使用是当你想要从一系列连续值的范围进行选择时。例如,假设我们想根据室外的温度打印出合适的活动,给出下列表:首先看一下,你也许试图为每个温度范围写一个分立If语句,可是进一步检查,就会清楚看到,这些

31、If条件是相互依赖的,即,如果语句中其中之一被执行其它的语句就不执行,我们确实是从一套可能性中选择一种选项在这种情况下,我们可以使用一个嵌套If结构作为一种多分支方法。这个问题和前面根据数字来打印月份名的例子之间的仅有的差别是,我们必须在If分支表达式中选择数字的范围。当范围是连续时,我们可以利用这种方法来使得我们的代码更有效。我们按照范围连续的次序来安排分支,然后,如果到达一个指定的分支,我们知道,先前的范围被从考虑的范围中除去,然而,If表达式必须只对每个范围最低值比较温度。cout 85 )cout ” swimming.” 70 )cout ” tennis.” 32 )cout ”g

32、olf.” 0 )cout ” string.” endl ;else cout ”dancing .” endl ;悬浮的else当If语句是嵌套式时,你也许发现你可能会把If-else配对混淆。即,哪一个If是else所属?例如,假设如果一个学生的平均分低于60,我们希望打印出 ” Failing ” ;如果平均分至少是60但小于70,我们想打印出 ”Passing but marginal ” ;如果是70或更大,我们不想打印出任何信息。我们在一个If-Then内,对这个信息用一个If-Then-Else嵌套编代码:if ( average 70.0 )if ( average 60.0

33、 )cout ” Failing ” ;else cout = 60.0 ) /不正确的版本if ( average 70.0 ) cout “ passing but marginal ” ;else cout = 60.0 ) /正确的版本 if ( average 70.0 ) cout “ passing but marginal” ;else cout ” Failing ” ;双花括号指出内部的if语句是完整的,所以else必须属于外面的if。 5.5 测试 I/O流的状态在第4章中,我们谈了C+中有关输入和输出流的概念,我们介绍了类istream,ostream,ifstream和ofstream。我们所说的下列任何一种情况都会引起输入流进入失败状态: 无效的输入数据 试图在文件结尾以外读数据 试图打

温馨提示

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

评论

0/150

提交评论