菜鸟的C++ 知识盲区(跌倒)到知识发现(爬起)---------第五章 语句

本章介绍的主要内容就是关于一些if  else 之类的语句,整体比前三章来说还是简单的。最近我开始在学python,因为工作项目上要用到它,发现python的整体语法结构还是比较简单的,相对来说,C++其实复杂点。但是C++的基础让我学习python上手很快。所以,我还是比较觉得C++就好九阳神功,有了九阳神功学习其他会事半功倍,而我的九阳神功练得还不是很好,所以继续看书,加强锻炼。这是题外话了,下面正式开始~!

5.1简单语句

c++语言中的大多数语句都以分号结束,一个表达式,比如ival + 5,末尾加上分号就变成了表达式语句(expression statement)。

最简单的语句是空语句(null statement),空语句中只含有一个单独的分号 ;但是!不要漏写分号,更重要的是也不要多写分号,请看下面的例子:因为while后面多了一个分号,导致整个程序的语法结构是改变的~~~~~这个切记!

// disaster: extra semicolon: loop body is this null statement
while (iter != svec.end()) ; // the while body is the empty st
++iter; // increment is not part of the loop

复合语句(compound statement)是指用花括号括起来的(可能为空的)语句和声明的序列,复合语句也被称作块(block)。一个块就是一个作用域(参见224节,第43页),在块中引入的名字只能在块内部以及嵌套在块中的子块里访问。所谓空块,是指内部没有任何语句的一对花括号。空块的作用等价于空语句。

5.2语句的作用域

可以在if、switch、while和for语句的控制结构内定义变量。定义在控制结构当中的变量只在相应语句的内部可见,一旦语句结束,变量也就超出其作用范围了,看下:i是在while定义的变量,但是脱离以后访问i是有问题的。

while (int i = get_num()) // i is created and initialized on each iteration
cout << i << endl;
i = 0; // error: i is not accessible outside the loop

5.3条件语句

if语句的作用是:判断一个指定的条件是否为真,根据判断结果决定是否执行另外一条语句。if语句包括两种形式:一种含有else分支,另外一种没有

if (condition)
statement

if (condition)
statement
else
statement2

通常情况下,为了避免嵌套if  else语句的歧义性,我们的代码规范中要求必须写上花括号。这么做的最大好处是避免语义不清楚。当一个if语句嵌套在另一个if语句内部时,很可能if分支会多于else分支。这个问题通常称作悬垂else (dangling else),在那些既有if语句又有if else语句的编程语言中是个普遍存在的问题。就c++来说它规定else与离它最近的尚未匹配的if匹配,从而消除了程序的二义性。

switch语句(switch statement)提供了一条便利的途径使得我们能够在若干固定选项中做出选择。见下例子:

// initialize counters for each vowel
unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
char ch;
while (cin >> ch) {
// if ch is a vowel, increment the appropriate counter
switch (ch) {
case 'a':
++aCnt;
break;
case 'e':
++eCnt;
break;
case 'i':
++iCnt;
break;
case 'o':
++oCnt;
break;
case 'u':
++uCnt;
break;
}
}
// print results
cout << "Number of vowel a: \t" << aCnt << '\n'
<< "Number of vowel e: \t" << eCnt << '\n'
<< "Number of vowel i: \t" << iCnt << '\n'
<< "Number of vowel o: \t" << oCnt << '\n'
<< "Number of vowel u: \t" << uCnt << endl;

不多解释:但是注意的是:case关键字和它对应的值一起被称为case标签(case label)。 case标签必须是整型常量表达式(参见2 4节,第58页),注意是整形常量表达式!!我之前还傻乎乎的搞一个字符串变量作为其标签原因就是没好好看书~~~~sb了我。如果程序没有任何一个case标签能匹配上switch表达式的值的时候,程序将会执行defualt标签。

还有swich语句可以作为状态机,在嵌入式编程中经常会遇到,所谓状态机就是书中讲的控制流,主要就是没有break,从一开始执行,如果满足再进入下一个状态:

switch(ch)
{
    case'a':
    {
        do………………
         ch='b';
    }
 case'b':
    {
        do………………
          ch='c';
    }
 case'c':
    {
        do………………
        ch='d';
    }
 case'd':
    {
        do………………
    }


}

书中所讲是统计出现元音字母的次数:

unsigned vowelCnt = 0;
// ...
switch (ch)
{
// any occurrence of a, e, i, o, or u increments vowelCnt
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
++vowelCnt;
break;
}

当然,在switch语句中还有一个可能让人忽略的问题:switch的执行流程有可能会跨过某些case标签。如果程序跳转到了某个特定的case,则switch结构中该case标签之前的部分会被忽略掉。这种忽略掉一部分代码的行为引出了一个有趣的问题:如果被略过的代码中含有变量的定义该怎么办?答案是:如果在某处一个带有初值的变量位于作用域之外,在另一处该变量位于作用域之内,则从前一处跳转到后一处的行为是非法行为。

case true:
// this switch statement is illegal because these initializations might be
bypassed
string file_name; // error: control bypasses an implicitly initialized variable
int ival = 0; // error: control bypasses an explicitly initialized variable
int jval; // ok: because jval is not initialized
break;
case false:
// ok: jval is in scope but is uninitialized
jval = next_num(); // ok: assign a value to jval
if (file_name.empty()) // file_name is in scope but wasn't initialized
//

所以赋值要在case作用域外~

5.4迭代语句

只要条件为真,while语句(while statement)就重复地执行循环体,它的语法形式是:

while (condition)
statement

和while语句很像的是do while 语句:二者区别是前者先判断后执行,后者先执行后判断。

do
    statement
while(condition)

传统的for语句是迭代语句的一个重要形式,结构为:

for (init-statement; condition; expression)
statement

一般情况下,init-statement负责初始化一个值,这个值将随着循环的进行而改变。condition作为循环控制的条件,只要condition为真,就执行一次statement.如果condition 第一次的求值结果就是false,则statement一次也不会执行。expression负责修改 init-statement初始化的变量,这个变量正好就是condition检查的对象,修改发生在每次循环迭代之后。statement可以是一条单独的语句也可以是一条复合语句。牢记for语句头中定义的对象只在循环体内可见。

for语句头能省略掉init-statement、condition和expression中的任何一个(或者全部)。C++ll新标准引入了一种更简单的for语句,这种语句可以遍历容器或其他序列的所有元素。范围for语句(range forstatement)的语法形式是:

for (declaration : expression)
statement

vector<int> v = {0,1,2,3,4,5,6,7,8,9};
// range variable must be a reference so we can write to the elements
for (auto &r : v) // for each element in v
r *= 2; // double the value of each element in v

5.5跳转语句

跳转语句记住两句话就够了:好好理解这两句话,真的很简单。

1.break语句(break statement)负责终止离它最近的while、do while、for或switch语句,并从这些语句之后的第一条语句开始继续执行。break语句只能出现在迭代语句或者switch语句内部(包括嵌套在此类循环里的语句或块的内部)。break语句的作用范围仅限于最近的循环或者switch:

2、continue语句(continue statement)终止最近的循环中的当前迭代并立即开始下一次迭代。continue语句只能出现在r、while和do while循环的内部,或者嵌套在此类循环里的语句或块的内部。和break语句类似的是,出现在嵌套循环中的continue语句也仅作用于离它最近的循环。和break语句不同的是,只有当switch语句嵌套在迭代语句内部时,才能在switch里使用continue。

goto语句其实不常用的,很多参考书建议我们不要用这个语句~~~但是我们公司的源码居然很多这个语句!!我不想吐槽了到此为止吧!其语法格式为:和switch语句一样,goto语句也不能将程序的控制权从变量的作用域之外转移到作用域之内:

goto label;
…………
label:
//eg:
goto end;
int ix = 10; // error: goto bypasses an initialized variable definition
end:
// error: code here could use ix but the goto bypassed its declaration
ix = 42;

5.6 try语句块和异常处理

如果程序中含有可能引发异常的代码,那么通常也会有专门的代码处理问题。例如,如果程序的问题是输入无效,则异常处理部分可能会要求用户重新输入正确的数据:如果丢失了数据库连接,会发出报警信息。异常处理机制为程序中异常检测和异常处理这两部分的协作提供支持。在c++语言中,异常处理包括:

throw表达式(throw expression),异常检测部分使用throw表达式来表示它遇到了无法处理的问题。我们说throw引发(raise)了异常。

try语句块(町block)'异常处理部分使用乜ry语句块处理异常。try语句块以关键字try开始,并以一个或多个catch子句(catchclause)结束。try语句块中代码抛出的异常通常会被某个catch子句处理。因为catch子句“处理”异常,所以它们也被称作异常处理代码(exception handler)。

一套异常类(exception class),用于在throw表达式和相关的catch子句之间传递异常的具体信息。

// first check that the data are for the same item
if (item1.isbn() != item2.isbn())
throw runtime_error("Data must refer to same ISBN");
// if we're still here, the ISBNs are the same
cout << item1 + item2 << endl;

在这段代码中,如果工SBN不一样就抛出一个异常,该异常是类型runtime error的对象。抛出异常将终止当前的函数,并把控制权转移给能处理该异常的代码。类型runtime error是标准库异常类型的一种,定义在stdexcept头文件中。关于标准库异常类型更多的知识将在5五3节(第176页)介绍。我们必须初始化 runtime error的对象,方式是给它提供一个string对象或者一个C风格的字符串

 try语法形式如下:

try {
program-statements
} catch (exception-declaration) {
handler-statements
} catch (exception-declaration) {
handler-statements
} // . . 

try语句块的一开始是关键字try,随后紧跟着一个块,这个块就像大多数时候那样是花括号括起来的语句序列。跟在try块之后的是一个或多个catch子句。catch子句包括三部分:关键字 catch、括号内一个(可能未命名的)对象的声明(称作异常声明,exception declaration) 以及一个块。当选中了某个catch子句处理异常之后,执行与之对应的块。catch一旦完成,程序跳转到try语句块最后一个catch子句之后的那条语句继续执行。try语句块中的program-statements组成程序的正常逻辑,像其他任何块一样, program-statements可以有包括声明在内的任意C++语句。一如往常,try语句块内声明的变量在块外部无法访问,特别是在catch子句内也无法访问。

c++标准库定义了一组类,用于报告标准库函数遇到的问题。这些异常类也可以在用户编写的程序中使用,它们分别定义在4个头文件中,这里就不一一介绍了!!下表为<stdexcept>定义的常见异常

第五章对于学过C的人来说并不难~我觉得最后的异常处理在平时的程序中所看到的并不是很多,下一步还要继续研究~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值