Swift 控制即時通行陳述式

來源:互聯網
上載者:User

標籤:swift   ios   objective-c   

控制即時通行陳述式(Control Transfer Statements)

控制轉移語句改變你代碼的執行順序,通過它你可以實現代碼的跳轉。Swift有四種控制轉移語句。

 

continue

break

fallthrough

return

我們將會在下面討論continue、break和fallthrough語句。return語句將會在函數章節討論。

 

 

Continue

continue語句告訴一個迴圈體立刻停止本次迴圈迭代,重新開始下次迴圈迭代。就好像在說“本次迴圈迭代我已經執行完了”,但是並不會離開整個迴圈體。

 

注意:

 

在一個for條件遞增(for-condition-increment)迴圈體中,在調用continue語句後,迭代增量仍然會被計算求值。迴圈體繼續像往常一樣工作,僅僅只是迴圈體中的執行代碼會被跳過。

下面的例子把一個小寫字串中的母音字母和空格字元移除,產生了一個含義模糊的短句:

 

let puzzleInput = "great minds thinkalike"var puzzleOutput = ""for character in puzzleInput {   switch character {   case "a", "e", "i", "o","u", " ":       continue   default:       puzzleOutput += character    }}println(puzzleOutput)   // 輸出 "grtmndsthnklk"


在上面的代碼中,只要匹配到母音字母或者空格字元,就調用continue語句,使本次迴圈迭代結束,從新開始下次迴圈迭代。這種行為使switch匹配到母音字母和空格字元時不做處理,而不是讓每一個匹配到的字元都被列印。

 

 

Break

break語句會立刻結束整個控制流程的執行。當你想要更早的結束一個switch代碼塊或者一個迴圈體時,你都可以使用break語句。

 

 

迴圈語句中的 break

 

當在一個迴圈體中使用break時,會立刻中斷該迴圈體的執行,然後跳轉到表示迴圈體結束的大括弧(})後的第一行代碼。不會再有本次迴圈迭代的代碼被執行,也不會再有下次的迴圈迭代產生。

 

 

Switch 語句中的 break

 

當在一個switch代碼塊中使用break時,會立即中斷該switch代碼塊的執行,並且跳轉到表示switch代碼塊結束的大括弧(})後的第一行代碼。

 

這種特性可以被用來匹配或者忽略一個或多個分支。因為 Swift 的switch需要包含所有的分支而且不允許有為空白的分支,有時為了使你的意圖更明顯,需要特意匹配或者忽略某個分支。那麼當你想忽略某個分支時,可以在該分支內寫上break語句。當那個分支被匹配到時,分支內的break語句立即結束switch代碼塊。

 

注意:

 

當一個switch分支僅僅包含注釋時,會被報編譯時間錯誤。注釋不是代碼語句而且也不能讓switch分支達到被忽略的效果。你總是可以使用break來忽略某個分支。

下面的例子通過switch來判斷一個Character值是否代表下面四種語言之一。為了簡潔,多個值被包含在了同一個分支情況中。

 

let numberSymbol: Character = "三"  // 簡體中文裡的數字 3var possibleIntegerValue: Int?switch numberSymbol {case "1", "?","一", "?":   possibleIntegerValue = 1case "2", "?","二", "?":   possibleIntegerValue = 2case "3", "?","三", "?":   possibleIntegerValue = 3case "4", "?","四", "?":   possibleIntegerValue = 4default:   break}if let integerValue = possibleIntegerValue{   println("The integer value of \(numberSymbol) is\(integerValue).")} else {   println("An integer value could not be found for\(numberSymbol).")}// 輸出 "The integervalue of 三 is 3."


這個例子檢查numberSymbol是否是拉丁,阿拉伯,中文或者泰語中的1到4之一。如果被匹配到,該switch分支語句給Int?類型變數possibleIntegerValue設定一個整數值。

 

當switch代碼塊執行完後,接下來的代碼通過使用可選綁定來判斷possibleIntegerValue是否曾經被設定過值。因為是可選類型的緣故,possibleIntegerValue有一個隱式的初始值nil,所以僅僅當possibleIntegerValue曾被switch代碼塊的前四個分支中的某個設定過一個值時,可選的綁定將會被判定為成功。

 

在上面的例子中,想要把Character所有的的可能性都枚舉出來是不現實的,所以使用default分支來包含所有上面沒有匹配到字元的情況。由於這個default分支不需要執行任何動作,所以它唯寫了一條break語句。一旦落入到default分支中後,break語句就完成了該分支的所有代碼操作,代碼繼續向下,開始執行if let語句。

 

 

貫穿(Fallthrough)

Swift 中的switch不會從上一個 case 分支落入到下一個 case分支中。相反,只要第一個匹配到的 case 分支完成了它需要執行的語句,整個switch代碼塊完成了它的執行。相比之下,C 語言要求你顯示的插入break語句到每個switch分支的末尾來阻止自動落入到下一個 case 分支中。Swift 的這種避免預設落入到下一個分支中的特性意味著它的switch 功能要比C 語言的更加清晰和可預測,可以避免無意識地執行多個 case 分支從而引發的錯誤。

 

如果你確實需要 C 風格的貫穿(fallthrough)的特性,你可以在每個需要該特性的 case 分支中使用fallthrough關鍵字。下面的例子使用fallthrough來建立一個數位描述語句。

 

let integerToDescribe = 5var description = "The number\(integerToDescribe) is"switch integerToDescribe {case 2, 3, 5, 7, 11, 13, 17, 19:   description += " a prime number, and also"   fallthroughdefault:   description += " an integer."}println(description)// 輸出 "The number 5is a prime number, and also an integer."


這個例子定義了一個String類型的變數description並且給它設定了一個初始值。函數使用switch邏輯來判斷integerToDescribe變數的值。當integerToDescribe的值屬於列表中的質數之一時,該函數添加一段文字在description後,來表明這個是數字是一個質數。然後它使用fallthrough關鍵字來“貫穿”到default分支中。default分支添加一段額外的文字在description的最後,至此switch代碼塊執行完了。

 

如果integerToDescribe的值不屬於列表中的任何質數,那麼它不會匹配到第一個switch分支。而這裡沒有其他特別的分支情況,所以integerToDescribe匹配到包含所有的default分支中。

 

當switch代碼塊執行完後,使用println函數列印該數位描述。在這個例子中,數字5被準確的識別為了一個質數。

 

注意:

 

fallthrough關鍵字不會檢查它下一個將會落入執行的case 中的匹配條件。fallthrough簡單地使代碼執行繼續串連到下一個 case 中的執行代碼,這和 C 語言標準中的switch語句特性是一樣的。

 

帶標籤的語句(Labeled Statements)

在 Swift 中,你可以在迴圈體和switch代碼塊中嵌套迴圈體和switch代碼塊來創造複雜的控制流程結構。然而,迴圈體和switch代碼塊兩者都可以使用break語句來提前結束整個方法體。因此,顯示地指明break語句想要終止的是哪個迴圈體或者switch代碼塊,會很有用。類似地,如果你有許多嵌套的迴圈體,顯示指明continue語句想要影響哪一個迴圈體也會非常有用。

 

為了實現這個目的,你可以使用標籤來標記一個迴圈體或者switch代碼塊,當使用break或者continue時,帶上這個標籤,可以控制該標籤代表對象的中斷或者執行。

 

產生一個帶標籤的語句是通過在該語句的關鍵詞的同一行前面放置一個標籤,並且該標籤後面還需帶著一個冒號。下面是一個while迴圈體的文法,同樣的規則適用於所有的迴圈體和switch代碼塊。

 

`label name`: while `condition` {   `statements`}


下面的例子是在一個帶有標籤的while迴圈體中調用break和continue語句,該迴圈體是前面章節中蛇和梯子的改編版本。這次,遊戲增加了一條額外的規則:

 

為了獲勝,你必須剛好落在第 25 個方塊中。

如果某次擲骰子使你的移動超出第 25 個方塊,你必須重新擲骰子,直到你擲出的骰子數剛好使你能落在第 25 個方塊中。

 

遊戲的棋盤和之前一樣:

 

 

 

值finalSquare、board、square和diceRoll的初始化也和之前一樣:

 

let finalSquare = 25var board = Int[](count: finalSquare + 1,repeatedValue: 0)board[03] = +08; board[06] = +11; board[09]= +09; board[10] = +02board[14] = -10; board[19] = -11; board[22]= -02; board[24] = -08var square = 0var diceRoll = 0


這個版本的遊戲使用while迴圈體和switch方法塊來實現遊戲的邏輯。while迴圈體有一個標籤名gameLoop,來表明它是蛇與梯子的主迴圈。

 

該while迴圈體的條件判斷語句是while square !=finalSquare,這表明你必須剛好落在方格25中。

 

gameLoop: while square != finalSquare {   if ++diceRoll == 7 { diceRoll = 1 }   switch square + diceRoll {   case finalSquare:       // 到達最後一個方塊,遊戲結束       break gameLoop   case let newSquare where newSquare > finalSquare:       // 超出最後一個方塊,再擲一次骰子       continue gameLoop   default:       // 本次移動有效       square += diceRoll       square += board[square]    }}println("Game over!")


每次迴圈迭代開始時擲骰子。與之前玩家擲完骰子就立即移動不同,這裡使用了switch來考慮每次移動可能產生的結果,從而決定玩家本次是否能夠移動。

 

如果骰子數剛好使玩家移動到最終的方格裡,遊戲結束。break gameLoop語句跳轉控制去執行while迴圈體後的第一行代碼,遊戲結束。

如果骰子數將會使玩家的移動超出最後的方格,那麼這種移動是不合法的,玩家需要重新擲骰子。continue gameLoop語句結束本次while迴圈的迭代,開始下一次迴圈迭代。

在剩餘的所有情況中,骰子數產生的都是合法的移動。玩家向前移動骰子數個方格,然後遊戲邏輯再處理玩家當前是否處於蛇頭或者梯子的底部。本次迴圈迭代結束,控制跳轉到while迴圈體的條件判斷語句處,再決定是否能夠繼續執行下次迴圈迭代。

注意:

 

如果上述的break語句沒有使用gameLoop標籤,那麼它將會中斷switch代碼塊而不是while迴圈體。使用gameLoop標籤清晰的表明了break想要中斷的是哪個代碼塊。同時請注意,當調用continue gameLoop去跳轉到下一次迴圈迭代時,這裡使用gameLoop標籤並不是嚴格必須的。因為在這個遊戲中,只有一個迴圈體,所以continue語句會影響到哪個迴圈體是沒有歧義的。然而,continue語句使用gameLoop標籤也是沒有危害的。這樣做符合標籤的使用規則,同時參照旁邊的break gameLoop,能夠使遊戲的邏輯更加清晰和易於理解。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.