5.1 简单语句
最简单的语句就是空语句(null statement),空语句中只含有一个单独的分号:
1 2 3 4 |
; //空语句 //重复读入数据直至到达文件末尾或某次输入的值等于sought while ( cin >> s && s != sought) ; //空语句 |
- 复合语句(compound statement)是指用花括号括起来的(可能为空的)语句和声明的序列,复合语句也被称作块(block)。一个块就是一个作用域。
5.2 语句作用域
可以在if、switch、while和for语句的控制结构内定义变量。定义在控制结构当中的变量只在相应语句的内部可见,一旦语句结束,变量也就超出其作用范围了。
5.3 条件语句
C++语言提供了两种按条件执行的语句。一种是if语句,它根据条件决定控制流;另一种是switch语句,它计算一个整型表达式的值,然后根据这个值从几条执行路径中选择一条。
- if语句:if statement 的作用是,判断一个指定的条件是否为真,根据判断结果决定是否执行另外一条语句。
- switch语句:switch statement提供了一条便利的途径使得我们能够在若干固定选项中做出选择。
1234567891011121314151617181920212223//为每个元音字母初始化其计数值unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;char ch;while(cin >> ch){//如果ch是元音字母,将其对应的计数值加1switch(ch){case 'a':++aCnt;break;case 'e':++eCnt;break;case 'i':++iCnt;break;case 'o':++oCnt;break;case 'u':++uCnt;break}}
case关键字和它对应的值一起被称为case标签(case label)。case标签必须是整型常亮表达式:
1234567char ch = getVal();int ival = 42;switch(ch){case 3.14: //错误:case标签不是一个整数case ival: //错误:case标签不是一个常亮//...}5.4迭代语句
迭代语句通常称为循环,它重复执行操作直到满足某个条件才停下来。while和for语句在执行循环体之前检查条件,do while语句先执行循环体,然后再检查条件。
- while语句:只要条件为真,while语句(while statement)就重复地执行循环体。定义在while条件部分或者while循环体内的变量每次迭代都经历从创建到销毁的过程。
- 传统的for语句:牢记for语句头中定义的对象只在for循环体内可见。
- 范围for语句:C++11新标准引入了一种更简单的for语句,这种语句可以遍历容器或其他序列的所有元素。范围for语句(range for statement)的语法形式是:
12for (declaration : expression)statement
expression表示的必须是一个序列,比如用花括号括起来的初始值列表、数组或者vector或string等类型的对象,这些类型的共同特点是拥有能返回迭代器的begin和end成员。declaration定义一个变量,序列中的每个元素都得能转换成该变量的类型,确保类型相容最简单的办法是使用auto类型说明符。 - 学习了范围for语句的原理之后,我们就不难理解为什么在3.3.2节强调不能通过范围for语句增加vector对象(或其他对象)的元素了。在范围for语句中,预存了end()的值。一旦在序列中添加(删除)元素,end函数的值就可能变得无效了。
- do while语句:do while 语句(do while statement)和while语句非常相似,唯一的区别就是,do while语句先执行循环体后检查条件。不管条件的值如何,我们都至少执行一次循环。do while语句的语法形式如下所示:
123dostatementwhile (condition);
NOTE:do while 语句应该在括号包围起来的条件后面用一个分号表示语句结束。5.5跳转语句
跳转语句中断当前的执行过程。C++语言提供了4种跳转语句:break、continue、goto、return 。
- break语句:break语句(break statement)负责终止离他最近的while、do while、for或switch语句,并从这些语句之后的第一条语句开始继续执行。
- continue语句:continue语句(continue statement)终止最近的循环中的当前迭代并立即开始下一次迭代。continue语句只能出现在for、while、do while循环体的内部,或者嵌套在此类循环体里的语句或块的内部。
- goto语句:goto语句(goto statement)的作用是从goto语句无条件跳转到同一函数内的另一条语句。goto语句的语法形式是 goto label; 其中,label是用于标识一条语句的标识符。带标签语句(labeled statement)是一种特殊的语句,在它之前有一个标示符以及一个冒号: end: return ; //带标签语句,可以作为goto的目标。goto语句和控制权转向的那条带标签的语句必须位于同一个函数之内。
5.6 try语句块和异常处理
典型的异常包括失去数据库连接以及遇到意外输入等,处理反常行为可能是设计所有系统最难的一部分。在C++语言中,异常处理包括:throw表达式(throw expression),异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发(raise)了异常。try语句块(try block),异常处理部分使用try语句块处理异常。一套异常类(exception class),用于在throw表达式和相关catch字句之间传递异常的具体信息。
- throw表达式:程序的异常检测部分使用throw表达式引发一个异常。throw表达式包含关键字throw和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。
12345//首先检查两条数据是否是关于同一种书籍的if (item1.isbn() != item2.isbn())throw runtime_error("Data must refer to same ISBN");//如果程序执行到了这里,表示两个ISBN是相同的cout << item1 + item2 << endl;
类型runtime_error是标准库异常类型的一种,定义在stdexcept头文件中。 - try语句块:异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句(catch clause)结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句处理异常,所以它们也被称作异常处理代码(exception handler)。try语句块通用语法形式是:
1234567try {program-statements}catch (exception-declaration) {handler-statements}catch (exception-declaration) {handler-statements}//...
catch子句包括三个部分:关键字catch、括号内一个(可能是未命名的)对象的声明(称作异常声明,exception declaration)以及一个块。
1234567891011121314while(cin >> item1 >> tiem2){try{//执行添加两个Sales_item对象的代码//如果添加失败,代码抛出一个runtime_error异常}catch (runtime_error err){//提醒用户两个ISBN必须一致,询问是否重新输入cout << err.what()<< "\nTry Again? Enter y or n " << endl;char c;cin >> c;if (!cin || c =='n')break; //跳出while循环}}
- 程序本来要执行的任务出现在try语句块中,这是因为这段代码可能回抛出一个runtime_error类型的异常。
- try语句块对应的catch子句,该子句负责处理类型为runtime_error的异常。如果try语句块的代码抛出了runtime_error异常,接下来执行catch块内的语句。
- 给用户的提示信息中输出了err.what()的返回值。我们知道err的类型是runtime_error,因此能推断what是runtime_error类的一个成员函数。每个标准异常类都定义了名为what的成员函数,这些函数没有参数,返回值是C风格字符串(即const char*)。其中,runtime_error的what成员返回的是初始化一个具体对象时所用的string对象的副本。如上代码抛出异常,输出:
12Data must refer to same ISBNTry Again? Enter y or n - 标准异常:C++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类可以在用户编写的程序中使用,它们分别定义在4个头文件中:
- exception头文件定义了最通用的异常类exception。它值报告异常的发生,不提供任何额外信息。
- stdexcept头文件定义了几种常用的异常类,详细信息在下标列出。
- new头文件定义了bad_alloc异常类型,这种类型将在12.1.2节介绍
- type_info头文件定义了bad_cast异常类型,这种类型将在19.2节介绍
异常处理看的不是很明白?