C++ primer第五章—语句

5.1 简单语句

5.1.1 空语句

  1. C++语言中的大多数语句都以分号结束,一个表达式加上 ; 就变成了 表达式语句(expression statement)。如果在程序的某个地方,语法上需要一条语句但是逻辑上不需要,则应该使用 空语句(null statement),空语句中只含有一个单独的分号 ;。
// 重复读入数据直至到达文件末尾或某次输入的值等于sought
while (cin >> s && s != sought)
    ;   		// 空语句

5.2 语句作用域

5.3 条件语句

5.3.2 switch语句

  1. switch 语句先对括号里的表达式求值,值转换成整数类型后再与每个 case 标签(case label)的值进行比较(case 标签必须是整型常量表达式,任何两个case标签不能相同)。如果表达式的值和某个 case 标签匹配,程序从该标签之后的第一条语句开始执行,直到到达 switch 的结尾或者遇到 break 语句为止。
  2. 通常情况下每个 case 分支后都有 break 语句,如果确实不应该出现 break 语句,最好写一段注释说明程序的逻辑。尽管 switch 语句没有强制一定要在最后一个 case 标签后写上 break,但为了安全起见,最好添加 break,这样即使以后增加了新的 case 分支,也不用再在前面补充 break 语句了。
unsigned vowelCnt = 0;
...
switch (ch){
	case 'a': case 'e': case 'i': case 'o': case 'u': 
		++vowelCnt;
		break;
	default:
		++otherCnt;
		break;
}
  1. 另外,switch 语句中可以添加一个 default 标签(default label),如果没有任何一个 case 标签能匹配上 switch 表达式的值,程序将执行 default 标签后的语句。即使不准备在 default 标签下做任何操作,程序中也应该定义一个 default 标签,其目的在于告诉他人我们已经考虑到了默认情况,只是目前不需要实际操作。

5.4 迭代语句

5.4.2 传统的for语句

for (initializer; condition; expression)
    statement
  1. initializer 中也可以定义多个对象,但是只能有一条声明语句,因此所有变量的基础类型必须相同。

5.4.3 范围for循环语句

for (declaration : expression)
    statement
  1. 其中 expression 表示一个序列,拥有能返回迭代器的begin 和 end 成员,比如用花括号括起来的初始值列表、数组或者者 vector 或 string 等类型的对象。declaration 定义一个变量,序列中的每个元素都应该能转换成该变量的类型(可以使用 auto)。如果需要对序列中的元素执行写操作,循环变量必须声明成引用类型,每次迭代都会重新定义循环控制变量,并将其初始化为序列中的下一个值,之后才会执行 statement。
  2. 范围for语句的定义来源于与之等价的传统for语句
vector<int> v = {O, 1, 2, 3, 4, 5, 6, 7, 8, 9};

// 范围变量必须是引用类型,这样才能对元素执行写操作
for (auto &r : v) 		// 对于v中的每一个元素
	r *= 2; 	
// 等价于<=>
for (auto beg = v.begin(), end = v.end(); beg != end; ++beg) {
	auto &r = *beg; 	// r必须是引用类型,这样才能对元素执行写操作
	// 也可以直接进行操作 *beg = *beg * 2;
	r *= 2; 			// 将v中每个元素的值翻倍
}

5.4.4 do-while语句

  1. 不允许在条件部分定义变量

5.5 跳转语句

5.5.3 goto语句

  1. goto 语句(labeled statement)是一种特殊的语句,它的作用是从 goto 语句无条件跳转到同一函数内的另一条语句,在它之前有一个标识符和一个冒号。
  2. 如果能不使用 goto 语句,强烈建议就不要使用了,因为它乱跳的缘故,使得程序既难理解又难修改。

5.6 try语句块和异常处理

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

5.6.1 throw表达式

  1. throw 表达式包含关键字 throw 和紧随其后的一个表达式,其中表达式的类型就是抛出的异常类型。throw 表达式后面通常紧跟一个分号,从而构成一条表达式语句。
  2. 抛出异常将终止当前函数,并将控制权转移给能处理该异常的代码
// 首先检查两条数据是否是关于同一种书籍的
if (item1.isbn() != item2.isbn())
	throw runtime_error("Data must refer to same ISBN");
// 如果程序执行到了这里,表示两个ISBN
cout << item1 + item2 << endl;

5.6.2 try语句块

  1. try 语句块的通用形式:
try {
    program-statements
} 
catch (exception-declaration) {
    handler-statements
} 
catch (exception-declaration) {
    handler-statements
} // . . .
  1. try 语句块中的 program-statements 组成程序的正常逻辑,其内部声明的变量在块外无法访问,即使在 catch 子句中也不行。语句块之后是 catch 子句,catch 子句包含:关键字 catch、括号内一个对象的声明(异常声明,exception declaration)和一个块。当选中了某个 catch 子句处理异常后,执行与之对应的块。catch 一旦完成,程序会跳过剩余的所有 catch 子句,继续执行后面的语句。
  2. 编写处理代码
while (cin >> item1 >> item2) {
	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循环
	}
}
  1. 寻找处理代码的过程与函数调用链刚好相反。当异常被抛出时, 首先搜索抛出该异常的函数。如果没找到匹配的 catch 子句, 终止该函数, 并在调用该函数的函数中继续寻找。如果还是没有找到匹配的 catch 子句,这个新的函数也被终止, 继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直至找到适当类型的 catch 子句为止。如果最终没能找到与异常相匹配的 catch 子句,程序会执行名为 terminate 的标准库函数。该函数的行为与系统有关,一般情况下,执行该函数将导致程序非正常退出。类似地,如果一段程序没有 try 语句块且发生了异常,系统也会调用 terminate 函数并终止当前程序的执行。

5.6.3 标准异常

  1. 异常类分别定义在4个头文件中:
  • 头文件 exception 定义了最通用的异常类 exception。它只报告异常的发生,不提供任何额外信息。
  • 头文件 stdexcept 定义了几种常用的异常类。
  • 头文件 new 定义了 bad_alloc 异常类。
  • 头文件 type_info 定义了 bad_cast 异常类。
    在这里插入图片描述
  1. 只能以默认初始化的方式初始化 exception、bad_alloc 和 bad_cast 对象,不允许为这些对象提供初始值。其他异常类的对象在初始化时必须提供一个 string 或一个C风格字符串,通常表示异常信息,但是不允许使用默认初始化的方式,且必须提供含有错误相关信息的初始值。异常类型只定义了一个名为what()的成员函数,该函数没有任何参数,返回值是一个指向C风格字符串的const char*。该字符串的目的是提供关于异常的文本信息。
  2. 标准库异常类只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值