循环和语句
① For 循环
for-in用来遍历一个区间(range),序列(sequence),集合(collection),系列(progression)里面所有的元素,执行一系列语句。
for条件递增(for-condition-increment)语句,用来重复执行一系列语句知道达成特定条件。一般通过在每次循环完成后增加计数器的值来实现。
for-in
<span style="font-size:24px;">for index in 1..5{
println("\(index) times 5 is \(index * 5)")
}
//1 times 5 is 5
//2 times 5 is 10
//3 times 5 is 15
//4 times 5 is 20</span>
当你不需要知道区间内每一项的值,可以使用下划线(_)代替变量名来忽略对值的访问:
<span style="font-size:24px;">let base = 3
let power = 10
var answer = 1
for _ in 1...power{
answer *= base
}
println("\(base) to power of \(power) is \(answer)")
//3 to power of 10 is 59049</span>
使用for-in遍历一个数组的所有元素:
<span style="font-size:24px;">let names = ["zhangsan","lisi","wanger","mazi"]
for name in names{
println(name)
}
//zhangsan
//lisi
//wanger
//mazi</span>
也可以通过遍历一个字典来访问他的键值对(key-value pairs)。遍历字典时,字典的每项元素会以(key,value)元组的形式返回,可以在for-in循环中使用显式的常量名称来解读(key,value)元组。
<span style="font-size:24px;">let numberOfLegs = ["Spider":8,"ant":6,"cat":4]
for (animalName,legCount) in numberOfLegs{
println("\(animalName) have \(legCount) legs")
}
//Spider have 8 legs
//ant have 6 legs
//cat have 4 legs</span>
字典元素的遍历顺序和插入顺序可能不同,字典的内容在内部是无序的,所以遍历元素时不能保证顺序。
也可以使用for-in循环来遍历字符串中的字符(Character):
for character in "hello" {
println(character)
}
//h
//e
//l
//l
//o
For条件递增(for-condition-increment)
Swift提供标准C语言for循环:使用条件判断和递增方法
<span style="font-size:24px;">for var index = 0; index < 3; index++ {
println("index is \(index)")
}
//index is 0
//index is 1
//index is 2</span>
下面是一般情况下的循环格式:
for initialization; condition; increment{}
和C一样,分号将循环的定义分为3个部分,不同的是,Swift不需要使用圆括号将3个部分包括起来.
也等同于:
initialization
while condition{
statements
increment
}
While循环
while循环运行一些列语句直到条件变成false。这类循环适合使用在第一次迭代前迭代次数未知的情况下。Swift提供两种while循环形式:
1. while循环,每次在循环开始时计算条件是否符合
2. do-while循环,每次在循环结束时计算条件是否符合
While循环从计算单一条件开始。如果条件为true,会重复运行一系列语句,直到条件变为false。
Do-while和While的区别是在判断循环条件之前,先执行一次循环代码快,然后重复循环直到条件为false
If
if语句最简单的形式就是只包含一个条件,当且仅当条件为true时,才执行相关代码。
if语句允许二选一,也就是当条件为false时,执行else语句。
Switch
switch语句会尝试把某个值与若干个模式(pattern)进行匹配。根据第一个匹配成功的模式,switch语句会执行对应的代码。当有可能的情况较多时,通常用switch替换if语句。
switch语句最简单的形式就是把某个值与一个或若干个相同类型的值做比较:
switch someValue to consider{
case value1:
respond to value1
case value2:
respond to value2
default:
otherwise, do something else
}
每一个case都是代码执行的一条分支,这与if语句类似。与之不同的是,switch语句会决定哪一条分支应该被执行。
switch语句必须是完备的。就是说,每一个可能的值都必须至少有一个case分支与之对应。在某些不可能涵盖所有值的情况下,你可以使用默认(default)分支满足该要求,这个默认分支必须在switch语句的最后面。
<span style="font-size:24px;">let oneCharacter: Character = "e"
switch oneCharacter{
case "a","e","i","o","u":
println("\(oneCharacter) is vowel")
case "b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z":
println("\(oneCharacter) is a consonant")
default:
println("\(oneCharacter) is not a vomel or a consonant")
}
//e is vowel</span>
与C和OC中的switch语句不通,在Swift中,当匹配的case分支中的代码执行完毕后,程序会终止switch语句,而不会继续执行下一个case分支。不需要在case分支中使用break语句。使得switch语句更安全,更易用。
注意:也可以在case分支中的代码执行完毕前跳出。
每一个case分支都必须包含至少一条语句。如果case分支是空的,则代码是无效的:
<span style="font-size:24px;">let oneCharacter: Character = "a"
switch oneCharacter{
case "a"://分支不能为空
case "A":
println("is A")
default:
println("NOT A")
}
// this will report a compile-time error</span>
一个case也可以包含多个模式,用逗号把它们分开。
如果想要贯穿至特定的case分支中,请使用fallthrough。
区间匹配(Range Matching):
case分支的模式也可以是一个值的区间。
<span style="font-size:24px;">let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount: String
switch count {
case 0:
naturalCount = "no"
case 1...3:
naturalCount = "a few"
case 4...9:
naturalCount = "several"
case 10...99:
naturalCount = "tens of"
case 100...999:
naturalCount = "hundreds of"
case 1000...999_999:
naturalCount = "thousands of"
default:
naturalCount = "millions and millions of"
}
println("There are \(naturalCount) \(countedThings).")
//There are millions and millions of stars in the Milky Way.</span>
元组(Tuple)
可以使用元组在同一个switch语句中测试多个值。元组中的元素可以是值,也可以是区间。使用下划线(_)来匹配所有可能的值。
<span style="font-size:24px;">let somePoint = (1,1)
switch somePoint{
case(0,0):
println("(0,0) is at the origin")
case(_,0):
println("(\(somePoint.0),0) is on the x-axis")
case(0,_):
println("(0,\(somePoint.1)) is on the y-axis")
case(-2...2,-2...2):
println("(\(somePoint.0),\(somePoint.1)) is inside the box")
default:
println("(\(somePoint.0),\(somePoint.1)) is outside of the box")
}
//(1,1) is inside the box</span>
和C语言不同,Swift允许多个case匹配同一个值。但是如果存在多个匹配,那么只会执行第一个匹配到的case分支。
值绑定(Value Bindings)
case分支的模式允许将匹配的值绑定到一个临时的常量或变量,这些常量或变量在该case分支里就可以被引用。
<span style="font-size:24px;">let anotherPoint = (2,0)
switch anotherPoint{
case (let x, 0):
println("on the x-axis with an x value of \(x)")
case (0,let y):
println("on the y-axis with an y value of \(y)")
case let(x,y):
println("somewhere else at (\(x),\(y))")
}
//on the x-axis with an x value of 2</span>
where
case 分支的模式可以使用where语句来判断额外的条件:
<span style="font-size:24px;">let yetAnotherPoint = (1,-1)
switch yetAnotherPoint{
case let(x,y) where x==y:
println("(\(x),\(y)) is on the line x == y")
case let(x,y) where x == -y:
println("(\(x),\(y)) is on the line x == -y")
case let(x,y):
println("(\(x),\(y)) is just some arbitrary point")
}
//(1,-1) is on the line x == -y</span>
控制转移语句(control,transfer,statements)
控制转移语句改变你的代码执行顺序,通过它你可以实现代码的跳转。
Swift有四种控制转移语句:
continue
break
fallthrough
return
Continue
continue语句告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。(本次循环迭代执行完了,但不会离开整个循环体)
注意:在一个for条件递增(for-condition-increment)循环体中,在调用continue语句中,迭代增量仍然会被计算求值。循环体继续像往常一样工作,仅仅只是循环体中的执行代码会被跳过。
let puzzleInput = "great minds thinks alike"
var puzzleOutput = ""
for character in puzzleInput{
switch character{
case "a","e","i","o","u"," ":
continue
default:
puzzleOutput += character
}
}
println(puzzleOutput)//grtmndsthnkslk
Break
break语句会立刻结束整个控制流的执行,当你想要更早的结束一个switch代码块或者一个循环体时,可以使用break。
循环语句中的break
当在一个循环体重使用break时,会立刻中断该循环体的执行,然后跳转到表示循环体结束的大括号{}后的第一行代码。不会再有本次循环迭代的代码被执行,也不会再有下次循环迭代产生。
Switch语句中的break
当在一个switch代码块中使用break时,会立即中断该switch代码块的执行,并且跳转到表示switch代码块结束的大括号{}后的第一行代码。
这种特性可以被用来匹配或者一个或多个分支。因为Swift需要包含所有的分支而且不允许有为空的分支,有时为了使你的意图更明显,需要特意匹配或者忽略某个分支。那么当你想忽略某个分支时,可以在该分支内写上break语句。当那个分支被匹配到时,分支内的break语句立即结束switch代码块。
注意:当一个swift分支仅仅包含注释时,会被报编译错误。注释不是代码语句而且不能让swift分支达到被忽略的效果。总是可以使用break来忽略某个分支。
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{
println("The integer value of \(numberSymbol) is \(integerValue).")
}else{
println("An integer value could not be found for \(numberSymbol).")
}
//The integer value of 三 is 3.
Swift中的switch不会从上一个case分支落入下一个case分支中。相反,只要第一个匹配到的case分支完成了它需要执行的语句,整个switch代码块完成了它的执行。相比之下,C要求你插入break语句到每个switch分支的末尾来阻止自动落入下一个case分支中。Swift的这种避免默认落入到下一个分支中的特性可以避免无意识的执行多个case分支从而引发的错误。
如果需要C风格的fallthrough特性,可以在每个需要该特性的case分支中使用fallthrough关键字。
<span style="font-size:24px;">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 alse"
fallthrough
default:
description += " an integer."
}
println(description)</span>
带标签的语句(Labeled Statements)
在Swift中,你可以在循环体和switch代码块中嵌套循环体和switch代码块来创造复杂的控制流结构。然而,循环体和switch代码块都可以使用break语句来提前结束整个方法体。所以指明break语句想要终止的是哪个循环体或者switch代码块是很有必要的。如果有许多嵌套的循环体,指明continue语句想要继续哪一个循环体也是很有必要的。
使用标签来标记一个循环体或者switch代码块,当使用break或者continue时,带上这个标签,可以控制该标签代表对象的中断或者执行。
产生一个带标签的语句是通过在该语句的关键词的同一行前面放置一个标签,并且该标签后面还需带一个冒号。
<span style="font-size:24px;">let integerToDescribe = 2
var description = "The number \(integerToDescribe) is"
someLoop: switch integerToDescribe{
case 2,3,5,7,11,13,17,19:
description += " a prime number, and alse"
break someLoop
case 1:
description += "a bitch"
default:
description += " an integer."
}
println(description)
//The number 2 is a prime number, and alse</span>