責編 | 歐陽姝黎
出品 | 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
if (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;evt
if (evt == BadNum)
return true;
return false;
改進后的代碼,當事件是壞的序號時,直接用return true返回,如果循環結束了還沒有return,那就返回false,使用return來代替break,這樣break語句和result這個變量,都一并被消除掉了,
可以說絕大部分的break和continue,都可以通過替換成return語句,或者翻轉if條件的方式來消除掉,變換后的代碼也會變得清晰很多,而一些含有復雜的邏輯的代碼,也可以通過提取一個幫助函數來消除掉。
總結
經驗總結幾個點,去掉break和continue的代碼變得容易理解,確保正確。
-
如果出現了continue,只需要把continue的條件反向,就可以消除continue。
-
如果出現了break,可以把break的條件,合并到循環頭部的終止條件里,從而去掉break,
-
可以把break替換成return,從而去掉break。
-
如果以上都失敗了,可以把循環里面復雜的部分提取出來,做一個幫助函數用來函數調用,之后continue或者break就可以去掉了。