第五章 控制流
3. Control Transfer Statements (控制转移语句)
控制转移语句将会更改执行代码时的顺序。将会把一段代码的控制权转移到另一段代码,swift语言一共有五种控制转移语句。continue
,break
,fallthrough
,return
,throw
。五种语句其中return将会写在函数相关章节里,throw在错误处理章节里面简单介绍过了。
3.1 Continue
continue语句一般都是用在循环语句中,当代码运行到continue的时候,他continue告诉这个循环体立刻停止本次循环,然后再重新开始下一轮的循环。continue就好像是在说:“本轮循环我已经执行完毕,但我不会停止继续循环,不会离开整个循环体” 下面这个例子可以说明
let puzzleInput = "great minds think alike"
var puzzleOutput = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in puzzleInput {
if charactersToRemove.contains(character) {
// 当常量值里面的某一个字符被移除后,循环不会停止继续下一轮循环,它要完成所有在常量字符串里面要被移除的每一个字符。
continue
}
puzzleOutput.append(character)
}
print(puzzleOutput)
3.2 break
break
会立即终止整个控制流的执行,当我们希望提前终止switch
或loop
语句的时候,可以在switch或loop语句中使用break,当在switch或loop语句中执行到想要的操作时整个控制流则会提前终止,控制流剩余的代码则不会被执行。
3.2.1 break in loop statement
break在loop语句中使用的时候,break会立即停止整个loop的执行并且将整个控制转移到loop的 }
(closing brace)之后。不会在继续执行下一轮loop的循环,操作会离开loop进入下一段代码的执行当中。
3.2.2 break in switch statement
当代码中的break在switch语句中执行的时候,break会立即停止执行 并且将整个控制转移带switch语句的 }
(closing brace)之后,这种操作会使得switch中的剩余case
被忽略掉不被继续执行,
let numberSymbol: Character = "三"
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
case "3", "٣", "三", "๓":
possibleIntegerValue = 3
case "4", "٤", "四", "๔":
possibleIntegerValue = 4
default:
break
}
if let integerValue = possibleIntegerValue {
print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
print("An integer value could not be found for \(numberSymbol).")
}
上面这个例子是用来检测numberSymbol是否含有这几种语言写的数字,case
的那几种情况。初始化给这个possiblenumber一个nil的值,后边会给他重新设置别的值所以我们要用变量var
关键字。一旦这个numberSymbol匹配到了一个和其中一个case有关的值。代码就回自动转移到整个switch语句之后了,那么就用可选绑定(if let
)来封装这个possibleIntegerValue被匹配到的值。
3.3 Fallthrough
case的写法不一样 其实用法和功效都是一样的 相比较break。
swift语言中的switch不会从上一个case的分支落入到下一个分支,代码执行不是这样的,相反的只有当switch匹配到一个case的时候整个switch语句就算是完成了她的工作了。继续进行下一段代码的工作。
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2, 3, 5, 7, 11, 13, 17, 19:
description += " a prime number, and also"
fallthrough
default:
description += " an integer."
}
print(description)
上面这个例子声明了一个新的复合String
变量, switch现在考虑的是这个integerToDescribe的值,如果这个值是2,3,5,7,9,11,13,17,19中的任意一个质数值,然后就会给这个变量后面加上switch语句里面的那段文字来表明这是一个质数值。然后他会使用fallthrough
关键字来将控制落入default
分支里面去,执行default分支在description的最后在添加一段文字,最终这个switch就算执行完了。
3.4 Labeled Statement (标签语句)
swift语言可以在一个循环(loop)或着条件语句(conditional statement)里面嵌套多个循环或者条件语句。 从而来组成一个复杂的控制流结构。循环和条件语句都可以使用break语句来永久性的终止执行。所以有时候我们在写代码的时候要清楚什么时候在哪里用这些控制转移关键字(break, continue)来执行哪些循环。我们可以在这个循环语句前面加一个标签来指明这是当前循环。下面是一个给while循环价格一个标签。
下面是用break和continue语句在给蛇和梯子游戏加一个标签的例子
gameLoop: while square != finalSquare {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch square + diceRoll {
case finalSquare: // fianlSquare=25
// 第一个case是如果摇骰子+当前的格子数刚好等于最后一个格子数break这个loop。代码则会转移控制到switch下一段代码(print语句)
break gameLoop
case let newSquare where newSquare > finalSquare:
// 封装并给出一个新的case 让这个新case中的newSquare大finalSquare, 继续重头执行这个gameLoop
continue gameLoop
default:
// this is a valid move, so find out its effect
square += diceRoll
square += board[square]
}
}
print("Game over!")
3.5 Early exit (提早退出)
提早退出的guard
语句其实和if语句比较相似,执行的时候都是取决于布尔值的true
或false
。guard语句要求这个布尔值必须是true的情况才能执行guard语句后面的代码。不像if语句guard语句必须要求由else从句,只有在布尔值不是true的情况才会执行else从句。
func greet(person: [String: String]) {
guard let name = person["name"] else {
return
}
print("Hello \(name)!")
guard let location = person["location"] else {
print("I hope the weather is nice near you.")
return
}
print("I hope the weather is nice in \(location).")
}
greet(person: ["name": "John"])
// Prints "Hello John!"
// Prints "I hope the weather is nice near you."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Prints "Hello Jane!"
// Prints "I hope the weather is nice in Cupertino."
只有guard语句的条件被满足的情况下,才会继续执行guard语句closing brace( }
)后面的代码,将变量或者常量的可选绑定作为语句的条件,都可以保护guard语句后面的代码能够被执行。
如果条件不被满足,在else从句上的代码就会被执行。这个从句必须转移控制以退出guard语句出现的代码段。它可以用控制转移语句(return , break , continue 或者 throw 做这件事,或者调用一个不返回的方法或函数,例如 fatalError() 。
相比于可以实现同样功能的if
语句,按需使用guard
语句会提升我们代码的可读性。它可以使你的代码连贯地被执行而不需要将它包在else块中,它可以使你在紧邻条件判断的地方,处理违规的情况。