如何避免循环中“突兀”的break和continue

百家 作者:CSDN 2021-03-04 22:01:54

责编 | 欧阳姝黎
出品 | CSDN(ID:CSDNnews)

循环里Continue,Break,Return经常会用到,也是很容易出错的一个坑,之前在循环里continue,break,return的作用,你知道吗? 说到过各自的用法,存在即合理,说能使用或者坚决不用没意义,这不是教条主义,但也有需要注意的地方,来打自己脸了。

循环语句(for,while)里面出现return是没什么问题的,但是如果使用了continue或者break语句,那么就会使得循环的逻辑和终止条件变得有些复杂起来了,尤其是在一些裸机比较绕的地方,难以保证其正确性。


为什么需要用continue或者break?


可以这么说,写代码的时候continue或者break的使用,往往是对循环的逻辑没有想的特别清楚。如果写代码的时候考虑周全了,理论上说是几乎不需要continue或者break的(欢迎举例反驳)。

那怎么办呢?有些逻辑确实也是需要,这种情况如果循环里出现了continue或者break,我们就应该考虑改写这个循环,让代码看着更简单易懂。


怎么改写continue或者break?


下面我对这些情况举一些例子。

情况1

下面这段代码里面有一个continue:

解释:如果其中一个事件等于一个坏的事件数,那么将跳过去,执行下一个状态。为了知道它到底在干什么,这里continue会导致一些语句被跳过了。

含有continue和break的循环不是那么容易理解,它们依靠控制流来描述逻辑,结果到最后很容易导致我们不能充分理解其中的涵义。

其实,我们只需要把continue的条件反向,这段代码就可以很容易的被转换成等价的,不含continue的代码:

解释:如果其中一个事件等于一个坏的事件数,那么将跳过去,执行下一个状态。为了知道它到底在干什么,这里continue会导致一些语句被跳过了。

pTrans = findTranss(pSM, evt);for(evt=0;evt<StateNum;evt++){  if (evt == BadNum)  {    continue;  }  pSM->state = pTrans->nextState;  ...}

含有continue和break的循环不是那么容易理解,它们依靠控制流来描述逻辑,结果到最后很容易导致我们不能充分理解其中的涵义。

其实,我们只需要把continue的条件反向,这段代码就可以很容易的被转换成等价的,不含continue的代码:

pTrans = findTranss(pSM, evt);for(evt=0;evt<StateNum;evt++){  if (evt != BadNum)  {      pSM->state = pTrans->nextState;      ...  }}

我们只需要把condition2反转之后,放到while头部的终止条件,就可以去掉这种break语句。更改后的代码如下:

while (condition1 && !condition2) {  ...}

表面上这种情况只适用于break出现在循环开头或者末尾的时候,然而在大部分时候,break都可以通过某种方式,移动到循环的开头或者末尾。

情况2

当 break 语句出现在一个for和while循环内时,循环会立即终止,且程序流将继续执行紧接着循环的下一条语句,break其实是给这个循环增加了一个退出条件。往往只需要把这个条件合并到循环头部,就可以去掉break。

比如下面这段代码,当condition2成立的时候,break就会退出循环:

while (condition1) {  ...  if (condition2) {    break;  }}

情况3

很多break退出循环之后,其实接下来就是一个return。这种break往往可以直接换成return。比如下面这个例子:

_Bool eventState{  _Bool result = false;  pTrans = findTranss(pSM, evt);  for(evt=0;evt<StateNum;evt++)  {    if (evt == BadNum)    {        result = true;        break;    }  }  return result;}

这个函数检查names链表里是否存在一个名字,包含“bad”这个词。它的循环里包含一个break语句。这个函数可以被改写成:

_Bool eventState{  _Bool result = false;  pTrans = findTranss(pSM, evt);  for(evt=0;evt<StateNum;evt++)  {    if (evt == BadNum)    {      return true    }  }  return false;}

改进后的代码,当事件是坏的序号时,直接用return true返回,如果循环结束了还没有return,那就返回false。使用return来代替break,这样break语句和result这个变量,都一并被消除掉了。

可以说绝大部分的break和continue,都可以通过替换成return语句,或者翻转if条件的方式来消除掉,变换后的代码也会变得清晰很多。而一些含有复杂的逻辑的代码,也可以通过提取一个帮助函数来消除掉。


总结


经验总结几个点,去掉break和continue的代码变得容易理解,确保正确。

  1. 如果出现了continue,只需要把continue的条件反向,就可以消除continue。

  2. 如果出现了break,可以把break的条件,合并到循环头部的终止条件里,从而去掉break。

  3. 可以把break替换成return,从而去掉break。

  4. 如果以上都失败了,可以把循环里面复杂的部分提取出来,做一个帮助函数用来函数调用,之后continue或者break就可以去掉了。

美团优选、多多买菜等五家社区团购被罚650万元;打车手机越贵,接单车型越贵;微软推出低代码语言 Power Fx | 极客头条
Google 重磅发布 Flutter 2 !一套代码横扫 5 大系统
亚马逊力推以太坊,微软谷歌准备跟进!
三年白干!程序员孙某因违反《竞业协议》赔偿腾讯 97.6 万元,返还 15.8 万元

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接