知识点:
1.范围for语句,前面讲过这里在提一下; 其中expression表示的必须是一个序列,比如用花括号括起来的初始值列表, 数组, 或者vector或string类型的对象,这些对象的共同特点是拥有能返回迭代器的begin和end成员。
declaration定义一个变量,
序列中的每个元素都能得到转换成该变量的类型
。确保类型相容最简单的办法使用auto类型说明符。每次迭代都会重新定义循环控制变量,并将其初始化成序列中的下一个值,之后才会执行statement。在范围for语句中,预存了end()的值。一旦在序列中添加(删除)元素,end函数的值就可能变的无效。
for
(declaration : expression)
statement;
2.break; 语句 负责终止离它最近的while,do while,for或switch语句,
并从跳出的语句后面的第一条语句开始继续执行,即break跳出当前的{}后,从这个{}后面的第一调语句开始执行。break语句只能出现在迭代语句或者switch语句内部,break语句的作用范围仅限于最近的循环或者switch。
3. continue 语句终止当前最近的循环中的当前迭代语句,并马上开始下一次迭代。continue语句只能出现在for 、while 、do while循环的内部,与break类似,也用于离它最近的循环。总之continue是中断当前的迭代,进行下一次循环。
4.异常是指存在于
运行时的反常行为,这些行为超出了函数正常功能的范围。典型的异常包括失去数据库连接以及遇到意外输入等。处理反常行为可能是设计所有系统最难的一部分。
5.当程序的某部分检测到一个它无法处理的问题时,需要用到异常处理。需要做3步:1 发出某种信号表面程序遇到某种故障,无法执行。2 信号发出必须明确在何处得到解决。3 发出异常信号,异常检测部分完成任务。
throw表达式,异常检测部分使用throw表达式来表示它遇到了无法处理的问题,我们说throw引发了异常。try语句块做异常处理,异常通常会被某个catch子句处理。
catch一旦完成,程序跳转到try语句块
最后一个catch子句之后的那条语句执行
。
6.throw 表达式语句,中断当前执行路径的表达式,存在于代码块中,将控制权转移到相关的catch子句,return 语句中值函数执行。
7.异常安全是一个术语,表示的含义是当抛出异常后,程序能执行正确的行为。
习题:
5.15 答:(a)for循环体内定义的作用域就在括号内; (b)for括号内部,缺少表达式; (c)ix与sz都自增,若sz!=0 ix无法追上sz, 死循环。
5.16 答:参考知乎大神的回答;
由于for语句将初始化,循环条件和每次循环后对循环变量的修改放在一起,比较清晰直观。因此for语句常用于能够预先判断循环次数的循环或遍历中。如遍历一个数组,或者执行某操作若干次之类。此时用for语句较优。
尽量明确缩小变量的作用范围。
while语句的历史更久,表达方式上更自由灵活,常用于无法事先判断循环次数的循环。譬如经典的计算C风格字符串的长度的代码,又如后根遍历二叉树的非递归实现。此时用while语句会使程序更清晰。
5.18 答:(a)do 后面缺少{}没有跟while匹配到一块; (b)不要再while内部定义判断条件,逻辑混乱 (c)while(ival) 无法访问ival,因为是在do{}语句块中 定义的,要记住每个{}定义的,都是个独立的逻辑块。
程序题:
#include
<iostream>
#include
<string>
#include
<vector>
using
namespace
std;
/*
判断两个vector,一个是否是另一个的前缀的
可以理解为一个是否按顺序包含另一个
*/
int
fun5_17()
{
int
a[5] = {1,2,3,4,5};
int
b[7] = {1,2,3,4,5,6,7};
vector<
int
> vec(a,a+5);
vector<
int
> vec1(b,b+7);
auto
len = vec.size() < vec1.size() ? vec.size():vec1.size();
for
(
decltype
(len) i = 0; i<len; ++i)
{
if
(vec[i] != vec1[i])
{
cout<<
"false "
<<endl;
return
0;
}
}
cout<<
"true"
<<endl;
return
0;
}
//使用do-while,循环输入单词,并输出较短的单词
void
fun5_19()
{
string word,word1,word2;
char
ch;
do
{
cout<<
"请输入两个单词: "
<<endl;
cin>>word1>>word2;
word = word1<word2 ? word1:word2;
cout<<
"较短的单词是: "
<<word<<endl;
cout<<
"是否继续? (y or Y): "
;
cin>>ch;
}
while
(ch ==
'y'
||ch ==
'Y'
);
}
//从标准输入流输入单词,当发生重复单词时break跳出并说明
//break只跳出for (do)while, switch等循环迭代语句,
void
fun5_20()
{
string word,word1,word2;
int
i = 0;
cout<<
"请输入单词: "
;
while
(cin>>word1>>word2)
{
if
(word1 == word2)
{
++i;
word = word1;
break
;
//这里退出while
}
}
if
(i != 0)
cout<<
"有连续重复单词出现:"
<<word<<endl;
else
cout<<
"没有重复的出现: "
<<endl;
}
//跟5.20一样,一次读取一个函数而不像上次那样两个一块读取
void
fun5_20(string name)
{
cout<<name<<endl;
string word1,word2;
while
(cin>>word2)
{
if
(word1 == word2)
{
break
;
}
else
word1 = word2;
}
if
(cin.eof())
// 返回流的结束位,当读取文件到达末尾时,eofbit 置1,eof()函数返回true
cout<<
"没有有重复单词"
<<endl;
else
cout<<
"有重复单词出现"
<<word1<<
"连续出现"
<<endl;
}
//找出开头是大写字母的重复单词
void
fun5_21()
{
string word1,word2;
bool
flg =
false
;
cout<<
"请输入单词: "
;
while
(cin>>word2)
{
if
(!isupper(word2[0]))
continue
;
if
(word1 == word2)
{
flg =
true
;
break
;
}
else
word1 = word2;
}
if
(flg)
cout<<
"有重复的以大写字母开头的单词"
<<word1;
else
cout<<
"false"
;
}
//除数为0的函数
void
fun5_23()
{
double
num1,num2;
cout<<
"请输入数字: "
;
cin>>num1>>num2;
cout<<num1/num2;
}
//除数为0,抛出异常
void
fun5_24()
{
double
num1,num2;
cout<<
"请输入数字: "
;
cin>>num1>>num2;
if
(num2==0)
throw
runtime_error(
"除数为0 !"
);
else
cout<<num1/num2;
}
void
fun5_25()
{
double
num1,num2;
cout<<
"请输入数字: "
;
while
(cin>>num1>>num2)
{
try
{
if
(num2==0)
throw
runtime_error(
"被除数为0 !"
);
cout<<
"重新输入两个数: "
;
}
catch
(runtime_error err)
//err 是runtime_error类的实例,返回内容编译器决定
{
cout<<err.what();
cout<<
"是否要重新输入? "
;
char
ch;
cin>>ch;
if
(ch ==
'n'
|| ch ==
'N'
)
break
;
}
cout<<
"catch执行完后,从这里继续继续执行: "
;
}
}
int
main()
{
//fun5_17();
//fun5_19();
//fun5_20();
//fun5_20("while 一次读一个单词");
//fun5_21();
//fun5_23();
//fun5_24();
fun5_25();
return
0;
}