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


責編 | 歐陽姝黎

出品 | 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;evtif (evt == BadNum){continue;}pSM->state = pTrans->nextState;...}

含有continue和break的循環不是那么容易理解,它們依靠控制流來描述邏輯,結果到最后很容易導致我們不能充分理解其中的涵義。

其實,我們只需要把continue的條件反向,這段代碼就可以很容易的被轉換成等價的,不含continue的代碼:

pTrans = findTranss(pSM, evt);for(evt=0;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{if (evt == BadNum){result = true;break;}}return result;}

這個函數檢查names鏈表里是否存在一個名字,包含“bad”這個詞。它的循環里包含一個break語句,這個函數可以被改寫成:

_Bool eventState{_Bool result = false;pTrans = findTranss(pSM, evt);for(evt=0;evtif (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就可以去掉了。

0 条回复 A文章作者 M管理員
    暫無討論,說說你的看法吧