C++ Primer 第五章
5.1 简单语句 & 条件语句
ival +5 ; //一条没有实际用处的表达式语句 cout << ival ; //有用的表达式语句 ; //空语句 //重复输入数据,直到文件末尾或输入的值等于 sought while(cin>>s && s!=sought) ; //语法需要 ival = v1 + v2;; //正确,第二个分号表示一条多余的空语句 while(iter != svec.end()); //出现糟糕的情况:额外的分号,循环体是那条空语句 ++iter; //递增运算不属于循环了 while(cin>>s && s!=sought){} //等价于空语句
语句的作用域
while(int i = get_num()) //每次迭代时创建并初始化 i cout << i << endl; i =0; //错误,在循环外部无法访问 //寻找第一个负值元素 auto beg = v.begin(); while(beg != v.end() && *beg >=0) ++beg; if(beg == v.end()) //v中所有元素大于等于0
条件语句
if 语句
//如果 grade 小于 60 分,对应的字面是 F,否则计算其下标 const vector<string> scores = {"F","D","C","B","A","A++"}; string lettergrade; if(grade < 60){ lettergrade = scores[0]; } else { lettergrade = scores[ (grade-50)/10 ]; }
switch 语句
如果表达式和某个 case 标签值匹配成功,就会从标签第一条语句开始执行,直到到达一条 break 或最尾部
5.2 迭代语句
迭代语句:循环
while 语句
vector<int> v; int i; while(cin >>i) v.push_back(i); //寻找第一个负值元素 auto beg = v.begin(); while(beg != v.end() && *beg >=0) ++beg; if(beg == v.end()) //v中所有元素大于等于0
传统for
//重复处理s中的字符直到处理完或遇到一个空白字符 for(decltype(s.size()) index =0; index != s.size() && !isspace(s[index]) ; ++index){ s[index] = toupper(s[index]); }
范围 for
vector<int> v = {0,1,2,3}; //范围变量必须是引用类型,这样才能对元素执行写操作 for(auto & r:v){ r *=2; //将v中每个元素的值都翻倍 } for(auto beg = v.begin(),end = v.end(); beg != end ; ++beg){ auto & r = *beg; r *=2; }
do while 语句
/* 不断提示用于输入一对数,然后求和 */ string rsp; //作为循环条件, do{ cout << "请输入两个数: "; int val1 =0,val2 =0; cin >> val1 >> val2; cout << " val1 + val2 = " << (val1 + val2) << endl; cin >> rsp; }while(!rsp.empty() && rsp[0] !='n'); //以分号结束
5.3 跳转语句 & 异常处理
break 语句:终止与其最近的 while,do while,for 或 switch 语句(跳出最近循环)
string buf; while( cin >> buf && !buf.empty()){ switch(buf[0]){ case '_': //... for(xx){break; }//离开循环体 break; //离开switch语句 case '+': } }
continue 语句:终止最近循环中的当前迭代并立即开始下一次迭代
string buf; while(cin>>buf && !buf.empty()){ if(buf[0] !='_' ) continue; //继续读取下一条输入 //程序执行到这里,说明当前输入是以下划线开始的 }
goto 语句:无条件跳转到同一个函数内的另一条语句
//... goto end; int ix =10; //错误 : goto语句绕过了一个带初始化的变量定义 end: //错误,此处代码使用ix ix =42; begin: //向后跳转一个带初始化的变量定义是合法的 int sz = get_size(); if(sz <=0){ goto begin(); //goto语句执行后,将销毁 sz }
try 语句块和异常处理:例如失去数据库连接或遇到异常输入
throw 表达式:异常检测部分使用 throw 表达式来表示遇到了无法解决的问题
runtime_error 是标准库异常类型的一种,定义在 stdexcept 头文件
Demo demo1,demo2; cin >> demo1 >> demo2; if(demo1.getId() == demo2.getId()){ cout << demo1.getId() << endl; return 0; //表示成功 } else { cerr << "Different ID" << endl; return -1; } //首先检查两个ID是否一样 if(demo1.getId() != demo2.getId()){ throw runtime_error("Different ID"); //抛出一个异常,终止当前函数,并把控制权交给处理异常的代码 }
try 语句块:异常处理部分使用 try 语句块处理异常,可以有一个或多个 catch
try{ //... } catch(runtime_error err){ cout << err.what() << endl; //返回的是初始化对象填入的参数 (const char*) }
一套异常类:throw 表达式和相关的catch子句之前传递异常的具体信息
这些异常分别被定义在四个头文件中
exception 头文件:最通常的异常类 exception ,只报告异常的发生,不提供额外信息
stdexcept 头文件:定义了几种常用的异常类
new 头文件:bad_alloc 异常类 (申请内存异常)
type_info 头文件:bad_cast 异常类 (类型处理异常)