C++ Primer第5章 语句

5.1 简单语句

表达式语句:一个表达式末尾加上分号,作用是执行表达式并丢弃掉求值结果,没什么用。
空语句:空语句只含有一个单独的分号。
如果程序某处语法上需要一条语句而逻辑上不需要,就应使用空语句。一种常见的情况是,当循环的全部工作在条件部分就可以完成时,我们通常使用空语句。
在这里插入图片描述
别漏写分号,也别多写分号。多余的空语句一般来说是无害的,但是如果在if或者while的条件后面跟了一个额外的分号,循环体就变成了那条空语句。
复合语句(块)
复合语句是指用花括号括起来的语句和声明的序列,也称为块。一个块就是一个作用域,在块中引入的名字只能在块内部以及嵌套在块中的子块里访问。
如果程序某处语法上需要一条语句,而逻辑上需要多条语句,则应该使用复合语句。例如,while和for循环的循环体。

5.2 语句作用域

可以在if、switch、while、和for语句的控制结构内定义变量。定义在控制结构当中的变量只在相应语句的内部可见,一旦语句结束,变量就超出其作用范围了。
如果其他代码也需要访问控制变量,则变量必须定义在语句的外部。
控制结构定义的对象必须初始化。

5.3 条件语句

两种按条件执行的语句。一种是if语句,它根据条件决定控制流;另一种是switch语句,它计算一个整型表达式的值,根据这个值从几条执行路径中选择一条。

5.3.1 if语句

if语句的作用是:判断一个指定的条件是否为真,根据判断结果决定是否执行另一条语句。if语句有两种形式:一种含有else分支,另一种不含有。
在这里插入图片描述
condition可以是表达式或者初始化了的变量声明,必须能转化成布尔类型。statement和statement2通常是块语句。

5.3.2 switch语句

switch语句提供了一条便利的途径使得我们能在若干固定选项中作出选择。
switch语句首先对括号中的表达式求值,表达式的值转化为整型类型,然后与每个case标签的值比较。如果表达式与某个标签的值匹配成功,程序从该标签之后的第一条语句开始执行,直到到达了switch的结尾或者遇到一条break语句为止。
case关键字和它对应的值一起被称为case标签,case标签必须是整型常量表达式。
在这里插入图片描述
每个case标签只能对应一个值,但是有时候我们希望两个或者更多个值共享同一组操作,此时,我们就故意省略掉break语句,使得程序能够连续执行若干个case标签。
在这里插入图片描述
尽管switch语句不是非得在最后一个标签后面写上break,但是为了安全起见,最号这样做。
default标签
如果没有一个 case标签能匹配上switch表达式的值,程序将执行紧跟在default标签后面的语句。
switch内部的变量定义
switch的执行流程有可能会跨过某些case标签,而被跨过的代码中可能含有变量的定义。C++语言规定不允许跨过变量的初始化语句直接跳转到该变量作用域的另一个位置。
如果需要为某个case分支定义并初始化一个变量,我们应该把变量定义在块内,从而确保后面的所有case标签都在变量的作用域之外。

5.4 迭代语句

迭代语句通常称为循环,它重复执行操作直到满足某个条件才停下来。while和for语句在执行循环体之前检查条件,do while 语句先执行循环体,然后再检查条件。

5.4.1 while语句

在这里插入图片描述
condition不能为空,如果condition第一次求值就得false,statement一次也不执行。
while的条件部分可以是一个表达式或者是一个带初始化的变量声明。定义在while的条件部分或者while循环体内的变量每次迭代都经历从创建到销毁的过程。
当不确定到底迭代多少次或者想在循环结束后访问循环控制变量,这时使用while循环比较合适。

5.4.2 传统的for语句

在这里插入图片描述
执行流程:
1.循环开始时,首先执行一次init-statement。inti-statement负责初始化一个值,这个值随着循环的进行而改变。
2.接下来判断condition。若第一次迭代时条件就为假,for循环体一次也不执行。
3.若条件为真,执行循环体。
4.最后执行expression。
for语句中定义的对象只在for循环体内可见。循环结束后,该对象便不可用。
for语句头中的多重定义
init-statement也可以定义多个对象,但是只能有一条声明语句,因此,所有变量的基础类型必须相同。
省略for语句头的某些部分
如果无须初始化,则我们可以使用一条空语句作为init-statement。分号必须保留,表示的是一个空的init-statement。
省略condition的效果等价于在条件部分写了一个true。在循环体内必须有语句负责退出循环。
也能省掉expression,但条件部分或循环体必须能改变迭代变量的值。

5.4.3 范围for语句

在这里插入图片描述
expression表示的必须是一个序列,比如用花括号括起来的初始值列表、数组或者vector或string等类型的对象,这些类型的共同特点是拥有能返回迭代器的begin和end成员。
declaration定义一个变量,序列中的每个元素都得能转换成该变量的类型。使用auto类型说明符。
每次迭代都会重新定义循环控制变量,并将其初始化成序列中的下一个值,之后才会执行statement。

5.4.4 do while语句

do while语句先执行循环体后检查条件,至少执行一次循环。
在这里插入图片描述
do while语句应该在括号包围起来的条件后面用一个分号表示语句结束。
condition使用的变量必须定义在循环体之外,不能定义在do的内部。
因为对于do while来说先执行语句或者块,后判断条件,所以不允许条件部分定义变量,否则变量的使用出现在定义之前,不合常理。

5.5 跳转语句

C++语言提供了4中跳转语句:break、continue、goto和return。

5.5.1 break语句

break语句负责终止离他最近的while、do while、for或switch语句,并从这些语句之后的第一条语句继续执行。

5.5.2 continue语句

continue语句终止最近的循环中的当前迭代并立即开始下一次迭代。只能出现在for、while和do while循环的内部,或者嵌套在此类循环里的语句或块的内部。

5.5.3 goto语句

goto语句的作用是从goto语句无条件跳转到同一函数内的另一条语句。
在这里插入图片描述
不要在程序中使用goto语句,因为它使得程序既难理解又难修改。

5.6 try语句块和异常处理

异常是指存在于运行时的反常行为,这些行为超出了函数正常功能的范围。当程序的某部分检测到一个它无法处理的问题时,需要用到异常检测。
异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。在C++语言中,异常处理包括:
1.throw表达式,异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发了异常。
2.try语句块,异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句处理异常,所以它们也被称为异常处理代码。
3.一套异常类,用于throw表达式和相关的catch子句之间传递异常的具体信息。

5.6.1 throw表达式

throw表达式包含关键字throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。
在这里插入图片描述
如果ISBN不同就抛出异常,该异常是类型runtime_error的对象。抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码。(runtime_error是标准库异常类型的一种,定义在stdexcept头文件中)

5.6.2 try语句块

在这里插入图片描述
try语句块的一开始是关键字try,随后紧跟着一个块。try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问。
catch子句包含三部分:关键字catch、括号内一个(可能未命名的)对象的声明(称为异常声明)以及一个块。当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。
在这里插入图片描述
在这里插入图片描述
程序本来要执行的任务出现在try语句块中,catch子句负责处理类型为runtime_error的异常。如果try语句块的代码抛出了runtime_error异常,接下来执行catch块内的语句。
给用户的提示信息中输出了err.what()的返回值。runtime_error的what成员返回的是初始化一个具体对象时所用的string对象的副本。

5.6.3 标准异常

C++标准库定义了一组类,用于报告标准库函数遇到的问题,分别定义在4个头文件中:1.exception头文件定义了最通用的异常类exception。它只报告异常的发生,不提供任何额外信息。2.stdexcept头文件定义了几种常见的异常类。3.new头文件定义了bad_alloc异常类型。4.type_info头文件定义了bad_cast异常类型。
在这里插入图片描述

发布了16 篇原创文章 · 获赞 11 · 访问量 643

猜你喜欢

转载自blog.csdn.net/qq_42820853/article/details/104550101