简单语句
(1)空语句
- 一种常见情况:当循环的全部工作在条件部分就可以完成时,会用到空语句
// 我们想要读取输入流的内容,直至遇到一个特定值,除此之外什么事情都不做
while(cin>>s&&s!=sought)
;
不要漏写分号,也不要在语句未结束时写分号
(2)符合语句(块)
块不以分号作为结束
语句作用域
- 在if、switch、while和for语句,在控制结构中声明的变量,只有在相应语句的内部可见,语句结束,则变量也超出其作用范围
条件语句
if语句
- if else语句的形式是
if(condition)
ststement
else
statement2
- 使用if else语句
const vector<string> scores={"F","D","C","B","A","A++"};
string lettergrade;
if (grade<60)
lettergrade=scores[0];
else
lettergrade=scores[(grade-50)/10];
- 嵌套if语句
// 加入的片段
if(grade % 10 > 7)
lettergrade += '+';
else if (grade % 10 < 3)
lettergrade += '-';
if(grade < 60)
lettergrade=scores[0];
else{
lettergrade=scores[(grade-50)/10];
if(grade != 100)
if(grade%10 > 7)
lettergrade +='+'';
else if(grade % 10<3)
lettergrade += '-'
}
- 悬垂else —— else 将会与最近的if匹配
switch语句
unsigned aCnt=0,eCnt=0,iCnt=0,oCnt=0,uCnt=0;
char ch;
while (cin>>ch){
switch(ch){
case 'a':
++aCnt;
break;
case 'e'
++eCnt;
break;
case 'i'
++iCnt;
break;
…
…
}
}
- case标签必须是整型常量表达式
(2)有时,默认的switch行为才是程序真正需要的。每个case标签只能对应一个值,但是有时候我们希望两个或更多个值共享一组操作,因此故意省略掉break语句
unsigned vowelCnt=0;
switch (ch){
case 'a':
case 'e':
case 'i':
case 'o':
case 'u';
++vowelCnt;
break;
}
漏写break容易引发缺陷
(3)default标签
(4)switch内部变量的定义
- 一般将变量的定义在case中用块包围,以免造成不必要麻烦
迭代语句
while语句
定义在while条件部分或者while循环体内的变量每次迭代都经历从创建到销毁的过程
vector<int> v;
int i;
while (cin>>i)
v.push_back(i);
auto beg=v.begin();
while (beg != v.end() && *beg>=0)
++beg;
传统for循环的执行流程
for(init-statemen;condition;expression)
statement
(1)传统for循环的执行流程
(2)for语句头中的多重定义
- init-statement可以定义多个对象,但是只能有一条声明语句
// 记录下v的大小,当达到原来的最后一个元素后结束循环
for(dealtype(v.size()) i=0,sz=v.size() ; i!=sz ; ++i)
v.push_back(v[i]);
(3)省略for语句头的部分
- 其中一种,省略expression
vector<int> v;
for(int i ; cin>>i ; /*表达式为空*/) //条件部分能够改变i的值,无需表达式部分
v.push_back(i);
范围for语句
- 形式如下
for(declaration : expression)
statement
- expression表示的必须是一个序列,比如用花括号括起来的初始值表、数组、vector、string等类型的对象,它们的共同特点是拥有能返回迭代器begin和end成员
- declaration定义一个变量,序列中每个元素都得能转换成该变量的类型,确保相容的最好办法是auto
vector<int> v={0,1,2,3,4,5,6,7,8,9};
for(auto &r : v)
r*+2;
do while语句
- 形式:
do
statement
while (condition);
- 小例子:不断提醒用户输入一对数,然后求其和
string rsp;
do{
cout<<"please enter two values: "
int val1=0,val2=0;
cin>>val1>>val2;
cout<<"The sum of them is: "<<val1+val2<<"\n\n"
"More?Enter yes or no:";
cin>>rsp;
}while(!rsp.empty()&&rsp[0]!='n');
- 因为do while想执行语句块,后判断条件,所以不允许在条件部分定义变量
跳转语句
break语句
- break语句:终止离它最近的while、do while、for或switch语句,并从这些语句之后的第一条语句开始继续执行
continue语句
- continue语句:终止最近的循环中的当前迭代并立即开始下一次迭代
string buf;
while(cin>>buf && !buf.empty())
if(buf[0] != '_')
continue; //接着读取下一输入
//程序处理到此处,即当前输入是以下划线开始的;接着处理buf……
}
goto语句
- goto语句:从goto语句无条件跳转到同一函数内的另一条语句
不要在程序中使用goto语句,因为它以理解和修改
goto label;
其中,label是用于标识一条语句的标示符,例如:“`end: return;“`
练习
do{
int sz=get_size();
}
while(sz<=0);
try语句块和异常处理
- 异常处理机制 为程序中异常检测和异常处理这两部分的协作提供支持,在C++中,异常处理包括:
- throws表达式
- 异常检测部分使用throw表达式来表示它遇到了无法处理的问题
- try语句块
- 异常处理部分使用try语句块处理异常
- try语句块以关键字try开始,并以一个或多个catch子句结
- try语句块中代码抛出的异常通常会被某一个catch字句处理
- 一套异常类
- 用于在throw表达式和相关的catch字句之间传递异常信息
- throws表达式
throw表达式
if(item1.isbn() != item2.isbn())
throw runtime_error("Data must refer to same ISBN");
// 程序执行到此,道标isbn号相同
cout<<item1+item2<<endl;
- 该异常是类型runtime_error的对象,其定义在stdexcept头文件中
try语句块
- 形式如下:
try{
program-statement
}catch(exception-declaration){
handler-statements
}catch(exception-declaration){
handler-statements
}//……
(1)编写处理代码
while(cin>>item1>>item2){
try{
//添加两个Sales_item对象的代码
//如果添加失败,代码抛出一个runtime_error异常
}catch(runtime_error err){
//提醒用户两个isbn必须一致
cout<<err.what()
<<"\n Try agin? Enter yes or no"<<endl;
char c;
cin>>c;
if(!cin || c=='n')
break; //跳出while循环
}
}
(2)函数在寻找处理代码的过程中退出
- 在寻找处理代码的过程与函数调用链刚好相反。当异常被抛出时,首先搜索抛出异常的函数。如果没有招到匹配的catch子句,终止该函数,并在调用该函数的函数中继续寻找。如果还是没有找到匹配的catch子句,这个新的函数也被终止,继续搜索调用它的函数。以此类推,沿着程序的执行路径逐层回退,直到招到适当类型的catch子句为止
- 如果最终还是没有找到任何匹配的catch子句,程序将自动转到名为terminate的标准库函数。该函数行为与系统有关,一般都将导致程序非正常退出
标准异常
- exception头文件定义了最常用的异常类exception。它只报告异常的发生,不提供任何额外的信息
- stdexcept头文件定义了几种常用的异常类
异常类 | 问题 |
---|---|
exception | 最常见的问题 |
runtime_erro | 只有在运行时才能检测出的问题 |
range_error | 运行时错误:生成的结果超出了有意义的值域范围 |
overflow_error | 运行时错误:计算上溢 |
underflow_error | 运行时错误:计算下溢 |
logic_error | 程序逻辑错误 |
domain_error | 逻辑错误:参数对应的结果值不存在 |
invalid_argument | 逻辑错误:无效参数 |
length_eroor | 逻辑错误:试图创建一个超出该类型最大长度的对象 |
out_of_range | 逻辑错误:使用一个超出有效范围的值 |
- new头文件定义了bad_alloc异常类型
- type_info头文件定义了bad_cast异常类型