注:本文为自己学习The Swift Programming Language的笔记,其中的例子为引用原书和其他博文或自己原创的。每个例子都会批注一些实践过程中的经验或思考总结。
1.基础
Swift支持所有类C语言常见的控制流结构,包括for和while循环语句、if和switch选择分支语句、break和continue转移语句等。
在传统的for-condition-increment循环基础上Swift引入了for-in循环,switch语句也有相应改变:case块不会陷入下一条执行,因而避免了C语言中常见的缺失break语句造成的错误;除此之外case语句能完成包括区间、元组以及值绑定不同类型的匹配,匹配值可以被绑定在一个常量或者变量上在case块中生效,而配合where关键词能完成更为复杂的匹配。
2.for循环
for循环就是在给定循环次数的情况下重复执行一段程序。
2.1for-in循环
for-in循环的作用是顺序遍历一遍集合类型的每个元素,比如区间范围的每个数、数组和字典里的每个数以及字符串中的每个字符。
因而,在in后面的集合类型有三种情况:区间(闭区间、半开半闭区间)、数组、字典和字符串。
区间、数组和字典的for-in循环在前面已经涉及很多例子了,这里就给出一个关于字符串的例子:
let definitionOfForInLoop = "You use the for-in loop to iterate over collections of items, such as ranges of numbers, items in an array, or characters in a string."
var countOfSpaceChar = 0
for char in definitionOfForInLoop {
if char == " " {
countOfSpaceChar++
}
}
println("\(countOfSpaceChar) space-characters in all.")
如果在循环中不会使用到每个元素的具体值,那么可以用下划线带替for和in中间元素名称声明的位置:
func Power(base : Int, power : Int) -> Int {
var answer = 1
for _ in 1...power {
answer *= base
}
return answer
}
println(Power(3,10))
2.2for-condition-increment循环
和所有类C语言的for循环用法一样,这里省略。for-condition-increment循环可以转化为while循环,但反之并不一定可行。
3.while循环
while循环是重复执行一段程序知道判断条件为false,常常用于事先并不知道重复次数的循环。
和其他类C语言一样,Swift支持两种while循环:一般while循环和do-while循环。它们之间仅有顺序上的不同:一般while循环是先判断条件condition是否为假,再执行循环体statement;而do-while循环是先执行循环体statement再判断条件是否为假。由于和其他类C语言用法一样,这里直接跳过。
4.条件语句
有时候某一段代码需要在某种条件成立的情况下才能执行,我们需要让这些代码条件化。Swift和其他类C语言一样,提供了两种条件分支语句if和switch。
4.1if语句
if语句支持else以及else-if等子块,需要注意的一点是判断条件,要么是Bool型要么是可空类型。
if-let配合可空类型使用时,let声明的常量只在if statement中起作用,即若可空类型是nil,则在else中不能引用该常量。
let optionalName : String? = "JCGuo"
if let name = optionalName {
println("Hello, \(name)")
}
else {
//you can not refer the const [name] here in else statement
}
4.2switch语句
switch语句用于将一个值和它可能的取值进行匹配比较,进而执行相应的代码。
Swift的switch是保证安全的,每一种取值必须考虑其中,因而在case不能一一枚举的情况下switch必须包含default块。与类C语言不同的是,Swift的switch并不支持隐式的向后陷入,因而不需要每个case块尾部必须添加break语句。并且由于取消隐式向后陷入,每一个case块中的statement不能为空。注意,Swift支持显式的向后陷入,需要使用fallthrough关键字。
一个case中可以包含很多取值,他们之间用逗号隔开;用冒号引出case块statement。
普通的switch用法跳过,我们直接来看switch的区间匹配、元组匹配。
(1)区间匹配
利用switch的区间匹配我们可以简化类C语言的if-else-if复合语句,让程序更简洁直观。例如,下面是中国科学技术大学的绩点计算方法:
func pointToGradePoint(point : Double)-> Double {
var gradePoint : Double
assert(point >= 0.0 && point <= 100.0,"Your point must be in the range [0,100]")
switch point {
case 95.0...100.0 : gradePoint = 4.3
case 90.0..95.0 : gradePoint = 4.0
case 85.0..90.0 : gradePoint = 3.7
case 82.0..85.0 : gradePoint = 3.3
case 78.0..82.0 : gradePoint = 3.0
case 75.0..78.0 : gradePoint = 2.7
case 72.0..75.0 : gradePoint = 2.3
case 68.0..72.0 : gradePoint = 2.0
case 65.0..68.0 : gradePoint = 1.7
case 64.0..65.0 : gradePoint = 1.5
case 61.0..64.0 : gradePoint = 1.3
case 60.0..61.0 : gradePoint = 1.0
default : gradePoint = 0.0
}
return gradePoint
}
println("Gosh, I got another \(pointToGradePoint(84.0))...")
(2)元组匹配
Swift的switch可以对元组进行多个值的匹配,元组的每个值可以和一个固定的值或者是一个区间匹配,使用下划线_来代表[任意取值]。
let somePoint = (1, 0)
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")
}
这是一个元组匹配的例子,涉及了区间和下划线的使用方法。由于case不会隐式的向后陷入,(1,0)落在x轴上并且也在正方形区域内,但只会输出它在x轴上(因为case块排在前面)。
(3)值绑定
switch的case可以把匹配的值绑定到一个变量或者常量上,以供在该case块中使用,用let或var完成:
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
println("on the x-axis with an x value of \(x)")
//println("on the x-axis with an x value of \(anotherPoint.0)")
case (0, let y):
println("on the y-axis with a y value of \(y)")
case let (x, y):
println("somewhere else at (\(x), \(y))")
}
其实值绑定相当于注释中的话,只是便于操作和修改。case let (x,y)相当于包括了所有其他情况,因此不需要default语句。
(4)where
Swift得switch语句可以使用where从句来检查附加条件,它的使用方法和英语中的定语从句一样,配合case选出满足where条件的元素。
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")
}
(x , y) where x == y一句表示,x和y相等的(x , y) 。
5.控制转移语句
Swift控制转移语句主要用来改变程序运行顺序,包括continue继续语句、break跳出循环语句、fallthrough显式向后陷入语句和return返回语句。
5.1continue语句和break语句
continue语句让循环跳过本次循环体中的其他语句直接进行下一次循环过程,注意条件判断并不会被跳过。
break语句用于直接终止所在的整个控制流,如在循环体中则终止当前一层循环(并不是所有循环),在Switch的case语句中终止当前switch语句。
由于continue和break的用法和类C语言一样,省略。
5.1fallthrough语句
在switch的case块中的最后一句显示的使用fallthrough关键字进行向后陷入,继续执行紧接着的case块中的语句:
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."
}
println(description)
// prints "The number 5 is a prime number, and also an integer.
如果这个数式质数不仅执行第一个case块中的语句,接着陷入default的语句中。
6.语句标签
由于Swift支持循环和switch分支的相互嵌套,相互嵌套会导致十分复杂的控制流结构。在使用break或continue语句时有时需要直接break或continue外层控制流,这时候就需要一个标签给语句一个名字,实现指定控制流break或continue。
在控制语句循环主体语句和分支主体语句的前面添加标签名,用冒号隔开。
[待补充]