本文知识点导图
简单语句
表达式后添加一个分号,就构成了表达式语句。
表达式语句的作用是执行表达式并丢弃掉求值结果。
空语句,最简单的语句时空语句。
别漏写分号,也别多写分号。
因为空语句时一条语句,所以可以用在任何允许使用语句的地方。所以,某些看起来非法的份好往往只不过是一条空语句而已。
多余的空语句一般来说是无害的,但是如果在if或while的条件后面跟了一个额外的份好就可能完全改变程序的初衷。
while (iter != svec.end() ) ; //错误,while循环体是这条空语句。
++iter;
复合语句(块)
复合语句是指用花括号括起来的语句和声明的序列,复合语句也被称为块。
一个块就是一个作用域。
如果在程序的某个地方,语法上需要一条语句,但是逻辑上需要多条语句,则应该使用复合语句。
语句作用域
在if,switch,while和for语句中控制结构内定义变量,定义在控制结构当中的变量只能在相应语句的内部可见,一旦语句结束,变量也就超出范围了。
条件语句
if语句
简单if语句
if(condition)
statement
if else语句
if(condition)
statement
else
statement2
在c++中,规定else与离他最近的尚未匹配的if匹配,从而消除程序的二义性。这个问题通常称为悬垂else。
switch语句
switch语句提供了一条便利的途径使得我们能够在若干固定选项中作出选择。
如下例,计算输入中每个元音字母的计数
unsigned aCnt = 0 , eCnt = 0, iCnt = 0, oCnt = 0,u Cnt = 0;
char ch;
while(cin >> ch){
switch (ch){
case 'a':
++aCnt;
break;
case 'e':
++eCnt;
break;
case 'i':
++iCnt;
break;
case 'o':
++oCnt;
break;
case 'u':
++uCnt;
break;
}
}
如果表达是和某个case标签匹配成功,程序从该标签之后的第一条语句开始执行,知道到达switch的结尾或者遇到一个条break语句为止。
default标签
如果没有任何一个case标签能匹配上switch表达式的值,程序将执行紧跟在default标签后面的语句。
迭代语句
while语句
while(condition)
statement
只要condition的求值结果为真,就一直执行statement。
如果condition第一次求值就得到了false,statement一次都不执行。
当不确定要迭代多少次,用while循环比较合适。
传统for语句
for (init-statement; condition; expression)
statement
执行过程如下:
- 循环开始时,首先执行一次init-statement;
- 接下来判断condition
- 如果真,执行循环体
- 最后执行expression
init-statement可以定义多个对象,但只能有一条声明语句。
for语句的三个部分都可以被省略掉。
范围for语句
for (declaration : expression)
statement
expression表示的必须是一个序列,比如用花括号括起来的初始值列表,数组或者vector或者string等类型的对象。
这些类型的共同特点是拥有能返回的迭代器begin和end成员。
do while语句
do while 语句和while语句十分相似,唯一的区别是,do while语句先执行循环体后检查条件。不管条件值如何,都至少执行一次循环
do
statement
while(condition);
condition不能为空,如果condition为假,循环终止,否则重复循环。condition使用的变量必须定义在循环体之外。
跳转语句
break语句
break语句负责终止离它最近的while,do while,for 或 switch 语句,并从这些语句之后的第一条语句开始执行。
break语句只能出现在迭代语句或switch语句内部。
continue语句
continue语句终止最近的循环中的当前迭代并立即开始下一次迭代。
continue语句只能出现在for、while和do while循环内部。
goto语句
goto语句的作用是从goto语句无条件跳转到同一函数内的另一条语句。
不要在程序中使用goto语句,因为它使得程序既难理解又难修改
goto label
label是用于表示一条语句的标识符。
带标签语句是一种特殊的语句在它之间有一个标识符以及一个冒号。如下
goto end;
...
end:
...
try语句块和异常处理
- throw表达式,异常检查部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发了异常。
- try语句块,异常处理部分使用try语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句结束。
- 一套异常类,用于在throw表达式和相关的catch子句之间传递异常的具体信息。
throw表达式
一个例子
if(item1.isbn() != item2.isbn())
throw runtime_error("Data must refer to same ISBN");
cout<< item1 + item2 <<endl;
runtime_error是标准库异常类型的一种,定义在stdexcept头文件中。
try语句块
try {
program-statements
}catch(exception-declaration){
handle-statements
}catch(exception-declaration){
handle-statements
}
例子
while(cin>> item1 >>item2){
try{
//执行throw例子中的代码,如果失败,抛出runtime_error异常
}catch(runtime_error err){
cout<<err.what()<<"\n Try Again? Enter y or n" <<endl;
char c;
cin >> c;
if(!cin || c == 'n')
break;
}
}
标准异常
C++标准库定义了一组类,用于报告标准库函数遇到的问题。
- exception头文件定义了最通用的异常类exception。他只报告异常发生,不提供额外信息
- stdexcept头文件定义了几种常见的异常类,见下表
- new头文件定义了bad_alloc异常类型。
- type_info头文件定义了bad_cast异常类型
类型 | 解释 |
---|---|
exception | 最常见的类型 |
runtime_error | 只有在运行时才能检测出的问题 |
range_error | 运行时错误,生成的结果超过了有意义的值域范围 |
overflow_error | 运行时错误,计算上溢 |
underflow_error | 运行时错误,计算下溢出 |
logic_error | 程序逻辑错误 |
domain_error | 逻辑错误,参数对应的结果值不存在 |
invalid_argument | 逻辑错误,无效参数 |
length_error | 逻辑错误,试图创建一个超出该类型最大长度的对象 |
out_of_range | 逻辑错误,使用一个超出有效范围的值 |