《C++Primer 第五版》——第五章 语句

5.1 简单语句

  1. C++ 中大部分语句都以分号结束,一个表达式末尾加上分号就变成了 表达式语句(expression statement) ,表达式语句的作用是执行表达式并丢弃掉表达式的值。
  2. 空语句(null statement) :最简单的语句,只有一个单独的分号—— ;一般空语句需要加上注释,解释为什么要省略(一般都是语法上需要一条语句,但逻辑上不需要时使用空语句)。
    所以下列的语句是正确的: int a;;这是一个定义语句后接一个空语句。
  3. 复合语句(compound statement),也被称为块(block) :是指用花括号 {}括起来的(可能为空的)语句和声明的序列。
    注意:
    ①在块中引进的变量名和常量名只能在块内部以及嵌套在块中的子块里访问
    块不以分号作为结束

5.2 语句作用域

  1. 可以在 if 、 switch 、 while 和 for 语句中定义变量,但是这些变量的生命周期在语句外就结束了。

5.3 条件语句

5.3.1 if 语句

  1. if 语句(if statement) :用于判断一个指定的条件是否为真,根据判断结果决定是否执行另一条语句。
  2. if 语句包含两种形式: if 语句和 if-else 语句
// if 语句
if (condition)
    statement
// if-else 语句
if (condition)
    statement1
else 
    statement2

其中 condition 可以是一个表达式或一个初始化了的变量声明,但前提是都可以转换成布尔类型。
对于 if 语句:如果 condition 的值为 true 则执行 statement ,若为 false ,则跳过 statement 。
对于 if-else 语句:如果 condition 的值为 true 则执行 statement1 ,若为 false ,则跳过 statement1 ,执行 statement2 。
3. if 语句和 if-else 都是可以嵌套使用的。
4. 悬挂 else (dangling else) :在既有 if 语句又有 if-else 语句的情况下, C++ 规定 else 与离它最近的尚未匹配的 if 匹配。
注意:

与 else 相匹配的 if 必须和它在同一作用域中。

if (n == 3)
{
   if (n == 4)
      return 1;
}  else        //这个 else 与第一行的 if 匹配
      return 0;

5.3.2 switch 语句

  1. switch 语句(switch statement) :用于在若干个固定选项中做出选择。
    下列是 switch 语句完整形式:
swicth (expression) {
      case  value1 :
                statement1;
                …………
                break;
      case  value2 :
                statement2;
                …………
                break;
      case  value3 :
                statemen3;
                …………
                break;
          ……………………
      default :
                statement_end;
}

switch 语句先对表达式 expression 求值(operand 也可以是一个初始化的变量声明),将值转换成整数,再与 case 标签的值比较。其中的 default标签和 break;语句可以省略。
如果匹配成功,则执行对应的语句直到遇到 break;语句或者 switch 的结尾为止。
如果没有匹配成功,若 switch 语句有用到 default标签,那么则执行 default 标签后的语句直到 switch 语句结束。
2. case 标签(case label)case关键字及其后面的值。
注意:

① case 标签的 值必须是整型常量表达式
② case 标签的值不能相同,否则就会引发错误

  1. switch 语句内部的控制流:如果某个 case 标签匹配成功,将从该标签开始向后执行语句,包括其它 case 标签,直到遇到 break 语句或 switch 语句结尾。
  2. default 标签(default label) :只由 default 关键字组成。如果没有一个 case 标签成功匹配,那么就执行 default 标签后的语句。
  3. 对于 switch 语句内部的变量定义:
       C++ 规定,不允许跨过变量的初始化语句直接跳转到该变量在作用域内的另一个位置。 如果在某处一个带有初始值的变量位于作用域外,在另一处改变量位于作用域内,则从前一处跳转到后一处的行为是非法行为。
    (后面的跳转语句也会提到)

5.4 迭代(循环)语句

5.4.1 while 语句

  1. while 语句(while statement) :只要条件表达式值为 true , while 语句就重复执行循环体。 while 语句形式如下:
while (condition)
      statement;

condition 一般是一个表达式或者是一个变量声明。
2. 定义在 while 的 condition 部分或 statement 部分的变量,在每次迭代时都会经历创建到销毁的过程。

5.4.2 for 语句

  1. for 语句(for statement) 的语法形式如下:
for (init-statement ; condition ; expression)
    statement;
  1. for 语句头 :关键字 for及括号里的部分。
  2. init-statement 必须是以下三种形式中的一种:声明语句、表达式语句、或者空语句。
  3. condition 是作为循环控制的条件,只要为真,就执行下去。
  4. expression 的执行时刻是在循环体 statement 之后。
  5. 在 for 循环语句内定义的对象只能在 for 语句内使用。
  6. init-statement 可以定义多个变量。
  7. for 语句头内的三个部分(init-statement 、 condition 、 expression)中的任何一个都可以省略,也就是空语句(或是全部省略)
  8. 其中的 condition 为空时,则相当于写了 true

5.4.3 范围 for 语句

  1. 范围 for 语句(range for statement) :这种语句可以遍历容器或其他序列的所有元素。语法形式如下:
for (declaration : expression)
    statement;
  1. 其中 expression 必须是一个序列,比如用花括号 {}括起来的初始值列表、数组或者 vector 或 string 等标准库容器类型的对象,这些类型的共同特点是拥有能返回迭代器的 begin 和 end 成员函数。
  2. declaration 定义一个循环控制变量,序列 expression 中的每个元素都可以转换成该变量的类型。
    注意: 如果要对序列 expression 中的元素执行写操作,循环变量必须声明为引用类型。
  3. 每次迭代都会重新定义循环控制变量,并将其初始化成序列中的下一个值,之后才会执行循环体 statement 。
  4. 注意 :不能通过 range-for 语句添加或删除 string 对象、 vector 对象或其他标准库容器类型对象的元素。也就是不能使用范围 for 语句改变容器类型对象和 string 对象的大小。

5.4.4 do-while 语句

  1. do-while 语句(do-while statement) :先执行循环体再检查条件。
    语法格式如下:
do
      statement;
while (condition) ;
  1. 不要忽略掉最后的分号 ;
  2. 不允许在 condition 部分定义变量。

5.5 跳转语句

5.5.1 break 语句

  1. break 语句(break statement) :负责终止 距离最近的 while 、 do-while 、 for 或 switch 语句 ,然后从终止语句之后的第一句语句开始执行。
  2. break 语句 只能出现在循环(迭代)语句和 switch 语句中。

5.5.2 continue 语句

  1. continue 语句(continue statement) :终止最近的循环语句中的当前迭代,并立即开始该循环语句的下一次迭代。
  2. 同样地, continue 语句 只能出现在while 、 do-while 、 for 循环语句的内部

5.5.3 goto 语句

  1. goto 语句(goto statement) :作用是从 goto 语句无条件的跳转到 同一函数 的标识符语句。语法格式如下:
// goto 语句
goto label;
//带标签语句 label 
label : 

其中 label 是用于标识一条语句的标识符,由用户自己编写。
2. 带标签语句(labeled statement) :是一种特殊的语句,语法格式: label :
3. 标签标识符独立于变量或其他标识符的名字,所以同名是合法的,没有任何影响。
4. 与 switch 语句类似, goto 语句同样不能将程序的控制权从变量的作用域之外转移到作用域之内。 也就是不能跳过变量的初始化。
5. 但是 goto 语句向后跳过一个已经执行的定义是合法的。
例如:

ttt :   
int a = 0;
while (true)
{
  goto ttt;
}

这会导致系统将销毁该变量,然后再创建它。
6. 带标签语句的标识符的命名格式:也是一样的由数字、下划线、英文字母组成,不能以数字开头。


5.6 try 语句块和异常处理

  1. 异常 :是指存在运行时的反常行为,这些行为超出函数正常功能的范围。例如:失去数据库连接以及遇到意外输入等。
  2. 异常处理机制 为程序中 异常检测和异常处理的协作 提供支持。
  3. 在 C++ 中,异常处理包括:
  • throw 表达式(throw expression) ,异常检测部分使用 throw 表达式来表示它遇到了无法处理的问题。我们通常说 throw 引发(raise) 了异常。
  • try 语句块(try block) ,异常处理部分使用 try 语句块来处理异常。 try 语句块以 try关键字开始,并以一个或多个 catch 子句(catch clause) 结束。 try 语句块抛出的异常通常会被某个 catch 子句处理。所以, catch 子句也被称作 异常处理代码(exception handler)
  • 异常类(exception class) :用于在 throw 表达式和相关的 catch 子句中间传递异常的具体信息。

5.6.1 throw 表达式

  1. throw 表达式 包含关键字 throw和后面的一个表达式,其中 表达式的类型就是抛出的异常的类型 。 throw 表达式后面跟着一个分号,从而构成一个表达式语句。
    例如:
if (item1.isbn() != item2.isbn())
    throw runtime_error("Data must refer to same ISBN");
else cout << item1 + item2 << endl;

在这串代码中,如果两个 isbn 不同,将抛出一个异常。该异常是类型 runtime_error 的对象。 抛出异常将终止当前函数,并把控制权转移到能处理该异常的代码(也就是跳转到能处理该异常的代码)。
其中的 runtime_error是标准库异常类型的一种,定义在 stdexcept 头文件中,可以通过使用一个 string 对象或一个 C 风格的字符串来初始化它。例如上述代码: runtime_error("Data must refer to same ISBN");,这个字符串中有关于异常的辅助信息。
2. throw关键字后表达式的类型可以是 内置数据类型

5.6.2 try 语句块

  1. try 语句块的语法形式:
try { 
    program-statements
} catch (exception-declaration) {
    handle-statements
} catch (exception-declaration) {
    handle-statements
} // ...

   try 语句块一开始是关键字 try,之后紧跟着一个块。跟在 try 块后的是一个或多个 catch 子句。
   catch 子句 包括三个部分:关键字 catch括号内一个(可能是未命名的)对象的声明 (称作 异常声明, exception declaration )以及一个块。
例如:

try
{
}
catch (runtime_error err) // runtime_error 类型的异常
{
	cout << err.what();
}
catch (int n) 
{
	cout << n;
}
catch (int)  //未命名的对象声明
{
}
  1. 当选中某个 catch 子句处理异常后,执行该 catch 子句的块,当执行完后,程序跳转到 try 语句块之后的第一条语句开始执行。
  2. 在 try 语句块的 program-statements 中也可以包含有声明在内的任意C++语句。同样地, try 块内声明的变量在块外是无法访问的,哪怕是 catch 子句的块。
  3. 抛出异常 :在复杂系统中,程序在遇到抛出异常的代码前,其执行的路径可能已经经过了多个try 语句块,例如一个 try 语句块可能嵌套了多个 try 语句块。
  4. 寻找处理异常代码 :当异常抛出时,首先搜索抛出异常的最内层函数,如果没找到对应的 catch 子句,则终止该函数,并在调用该函数的外层函数中继续搜索,反复直到找到对应的 catch 子句。
      如果最后还是没有找到对应的 catch 子句,则程序跳转到名为 terminate 的标准库函数。 该函数的行为与系统有关,执行该函数一般会导致程序非正常退出。
  5. 异常中断了程序的正常流程。 异常发生时,调用者请求的一部分计算可能完成,另一部分可能还未完成。通常情况下,略过部分程序意味着某些对象处理到一半就戛然而止,从而导致对象处于无效或者未完成的状态,或者资源没有正常释放等等。
  6. 异常安全(exception safe)的代码 :在异常发生期间正确执行“清理”工作的程序。
  7. 对于处理异常后继续执行的程序,我们必须时刻注意异常是何时发生的,异常发生后程序如何确保对象有效、资源无泄漏、程序处于合理状态,等等。
  8. 每个标准库异常类都定义了名为 what 的成员函数,这些函数都不接受参数,且都返回一个指向 const 的C风格字符串的指针(即 const char* )。

5.6.3 标准异常

  1. C++ 标准库定义了一组类,用于报告标准库函数遇到的问题。
  2. 这些类分别定义在4个头文件中
  • exception 头文件定义了最通用的异常类 excepttion 。它只报告异常的发生,而不提供任何额外信息。
  • stdexcept 头文件定义了集中常见的异常类。
  • new 头文件定义了 bad_alloc 异常类型。
  • type_info 头文件定义了 bad_cast 异常类型。
  1. 标准库异常类只定义了几种运算,包括创建或拷贝异常类型的对象,以及为异常类型的对象赋值。我们只能以默认初始化的方式初始化 exception 、 bad_alloc 和 bad_cast 对象,不允许为它们提供初始值。
      其他异常类型的行为则恰好相反:应该使用 string 对象或者 C 风格字符串初始化这些类型的对象,但是不允许使用默认初始化的方式。当创建此类对象时,必须提供初始值,该初始值包含有错误相关的信息。
  2. 异常类型只定义了一个名为 what 的成员函数,该函数无参数,返回值是一个指向 C 风格字符串的 const char*。该字符串的作用是提供关于异常的一些文本信息。
    成员函数​ what 返回的 C 风格字符串的内容与其他异常对象的类型有关。如果异常类型有一个字符串初始值,则 what 返回该字符串。对于其他无初始值的异常类型来说,what 返回的内容也由编译器决定。

5.7 return 语句

1.return 语句的作用是终止整个函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《C Primer》是一本针对C语言初学者的经典教材,第五版的第六章主要介绍了函数的基本概念和用法。 在第六章中,教材首先介绍了函数的定义和调用。函数是具有独立功能的代码块,可以通过函数名来调用。函数由函数头、参数、函数体和返回值组成。函数头包括函数类型、函数名和参数类型,参数用于接收传递给函数的值,返回值用于将结果返回给调用者。 接着,教材详细介绍了函数的参数传递方式,包括按值传递、按引用传递和按指针传递。按值传递是指将参数的值复制给形参,按引用传递是指将参数的引用传递给形参,而按指针传递是将参数的地址传递给形参。不同的传递方式在函数内部对参数进行操作时,会对应不同的结果。 此外,教材还讲解了函数的返回值和函数的调用顺序。函数的返回值类型由函数头中的类型确定,可以是任意类型。当函数需要返回多个值时,可以使用结构体或指针进行返回。函数的调用顺序决定了函数执行的顺序,即哪个函数先执行,哪个函数后执行。 在函数的实现过程中,教材介绍了函数的定义和声明、局部变量和全局变量、递归等内容。通过这些知识点的学习,读者可以了解到函数的具体细节和一些实践技巧。 总的来说,第五版的第六章通过清晰的语言和丰富的例子,循序渐进地讲解了函数的基本概念和用法。学完这一章,读者将能够理解函数的定义、调用、参数传递、返回值和实现等方面的知识,为之后的学习和实践打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值