//***********swift学习之14--控制流--***************************
// 1.控制流有哪些?
/*
Swift提供了所有C语言中相似的控制流结构。包括for和while循环;if和switch条件语句;break和continue跳转语句等。 Swift还加入了for-in循环语句,让编程人员可以在遍历数组,字典,范围,字符串或者其它序列时更加便捷。
相对于C语言,Swift中switch语句的case语句后,不会自动跳转到下一个语句,这样就避免了C语言中因为忘记break而造成的错误。另外case语句可以匹配多种类型,包括数据范围,元组,或者特定的类型等。switch语句中已匹配的数值也可以被用在后续的case语句体中,where关键词还能被加入任意的case语句中,来增加匹配的方式。
*/
// 1.1 for循环的一般结构
// swift 3.0 推荐这种
var index1: Int = 0
for index1 in 0 ..< 3 { // ..两个点
print("index is \(index1)") // index 不会
}
print("The loop statements were executed \(index1) times")
// 在上面的例子中,index在每一次循环开始前都已经被赋值,因此不需要在每次使用前对它进行定义。每次它都隐式地被定义,就像是使用了let关键词一样。注意index是一个常量。
// 注意:index只在循环中存在,在循环完成之后如果需要继续使用,需要重新定义才可以。
// 1.2 for in循环
// 如果你不需要序列中的每一个值,可以使用_来忽略它,仅仅只是使用循环体本身:
let base = 3
let power = 10
var answer = 1
for _ in 1...power { // 三个点
answer *= base
}
// 3的10 次方
print("\(base) to the power of \(power) is \(answer)")
// 1.3 for in循环遍历数组的元素
let forRoopArray = ["zhanSan","liSi","xiaoMing","xiaoFang"]
for name in forRoopArray {
print("hello \(name)!")
}
// 1.4 for in循环遍历字典的元素
let numOfLegs = ["spider":8,"ant":6,"cat":4]
for (animalName,legCount) in numOfLegs {
print("\(animalName) 有\(legCount)条腿")
}
// 1.5 我们也可以使用enumerate()方法来进行字典遍历,返回的是字典的索引及 (key, value) 对,实例如下:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerated() {
print("字典中index \(key) 对应的键值对 \(value)")
}
// 2 while循环
// while循环执行一系列代码块,直到某个条件为false为止。这种循环最长用于循环的次数不确定的情况。Swift提供了两种while循环方式:
// (1)while循环,在每次循环开始前测试循环条件是否成立
// (2)repeat-while循环,在每次循环之后测试循环条件是否成立
// 2.1 while循环
// while循环由一个条件语句开始,如果条件语句为true,一直执行,直到条件语句变为false。
let finalSquare = 25
var board = Array (repeating: 0 , count: finalSquare + 1 )
var board1 = [Int] (repeating: 0, count: finalSquare + 1)
var board2 = [Float] (repeating: 0.5, count: finalSquare + 1)
board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
var square = 0
var diceRoll = 0
while square < finalSquare {
// roll the dice
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
// move by the rolled amount
square += diceRoll
if square < board.count {
// if we're still on the board, move up or down for a snake or a ladder
square += board[square]
}
}
print("\(square) == \(finalSquare) Game over!")
// 2.2 repeat-while循环
// 另一种while循环是repeat-while循环。在这种循环中,循环体中的语句会先被执行一次,然后才开始检测循环条件是否满足,下面是repeat-while循环的一般形式
let doFinalSquare = 25
var doBoard = [Int](repeating: 0, count: doFinalSquare + 1)
doBoard[03] = +08; doBoard[06] = +11; doBoard[09] = +09; doBoard[10] = +02
doBoard[14] = -10; doBoard[19] = -11; doBoard[22] = -02; doBoard[24] = -08
var doSquare = 0
var doDiceRoll = 0
repeat {
// move up or down for a snake or ladder
doSquare += doBoard[doSquare]
// roll the dice
doDiceRoll += 1
if doDiceRoll == 7 { doDiceRoll = 1 }
// move by the rolled amount
doSquare += doDiceRoll
} while doSquare < doFinalSquare
print("\(doSquare) == \(doFinalSquare) Game over!")
// 3 条件语句
// 3.1 if 语句 很简单不再赘述
// 3.2 switch 语句
// 在switch中,每一个case分支都会被匹配和检测到,所有case没有提到的情况都必须使用default关键词。注意default关键词必须在所有case的最后。
// 下面的例子用switch语句来判断一个字符的类型:
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
}
// prints "e is a vowel"
// 跟C和Objective-C不同,Swift中的switch语句不会因为在case语句的结尾没有break就跳转到下一个case语句执行。switch语句只会执行匹配上的case里的语句,然后就会直接停止。这样可以让switch语句更加安全,因为很多时候编程人员都会忘记写break。
// 每一个case中都需要有可以执行的语句,下面的例子就是不正确的:
let anotherCharacter: Character = "a"
switch anotherCharacter {
//case "a":
//case "A":
// println("The letter A")
default:
print("Not the letter A")
}
// 跟C不同,switch语句不会同时匹配a和A,它会直接报错。一个case中可以有多个条件,用逗号,分隔即可:
switch anotherCharacter {
case "a","A":
print(" the letter is A or a")
default:
print("Not the letter A or a")
}
// 3.3范围匹配
// switch语句的case中可以匹配一个数值范围,比如:
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...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"
}
print("There are \(naturalCount) \(countedThings).")
// 3.4 元组 case中还可以直接测试元组是否符合相应的条件,_可以匹配任意值。
// 下面的例子是判断(x,y)是否在矩形中,元组类型是(Int,Int)
var imageView:NSImageView = NSImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
imageView.image = NSImage(named: "image_thumb.png")
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
print("(0, 0) is at the origin")
case (_, 0):
print("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
print("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
print("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
print("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}
// 3.5 数值绑定
// 在case匹配的同时,可以将switch语句中的值绑定给一个特定的常量或者变量,以便在case的语句中使用。比如:
let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
print("on the x-axis with an x value of \(x)")
case (0, let y):
print("on the y-axis with a y value of \(y)")
case let (x, y):
print("somewhere else at (\(x), \(y))")
}
// 3.6 Where关键词
// switch语句可以使用where关键词来增加判断的条件,在下面的例子中:
let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
print("(\(x), \(y)) is just some arbitrary point")
}
// 4、控制跳转语句
// continue、break、fallthrough、return
// 其中continue,break和fallthrough在下面详细介绍,return语句将在函数一章介绍。
// 4.1 continue语句告诉一个循环停止现在在执行的语句,开始下一次循环。
// 注意:在for-condition-increment循环中,increment增量语句依然执行,只是略过了一次循环体。
// 下面的例子实现的是去除一个字符串中的空格和元音字母,从而组成一个字谜:
let puzzleInput:String = "great minds think alike"
var puzzleOutput = ""
for character in puzzleInput.characters {
switch character {
case "a", "e", "i", "o", "u", " ":
continue
default:
puzzleOutput += String(character)
}
}
print(puzzleOutput)
// 4.2 break
// break语句将终止整个循环的执行,可以用在循环语句中,也可以用在switch语句中。
// swift 中的break不写也会匹配后跳出
let numberSymbol: Character = "三" // Simplified Chinese for the number 3
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "١", "一", "๑":
possibleIntegerValue = 1
case "2", "٢", "二", "๒":
possibleIntegerValue = 2
case "3", "٣", "三", "๓":
possibleIntegerValue = 3
case "4", "٤", "四", "๔":
possibleIntegerValue = 4
print("The integer v")
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).")
}
// 4.3 fallthrough
// 由于Swift中的switch语句不会自动的因为没有break而跳转到下一个case,因此如果需要想C语言中那样,依次执行每个case的时候,就需要用到fallthrough关键词。
// 像下面这个例子一样,default分支最终都会被执行:
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)
// 4.5 标签语句
// switch和循环可以互相嵌套,循环之间也可以互相嵌套,因此在使用break或者continue的时候,需要知道到底是对哪个语句起作用。这就需要用到标签语句。标签语句的一般形式如下:
//label name: while condition {
// statements
//}
// 下面的例子演示了如何使用标签语句以及嵌套的循环和switch。
// 依然采用之前的那个梯子与蛇的游戏,第一步依然是设置初始值:
let finalSquare112 = 25
var board112 = [Int](repeating: 0, count: finalSquare112 + 1)
board112[03] = +08; board112[06] = +11; board112[09] = +09; board112[10] = +02
board112[14] = -10; board112[19] = -11; board112[22] = -02; board112[24] = -08
var square112 = 0
var diceRoll112 = 0
// 然后,使用一个while循环与switch的嵌套来完成游戏
gameLoop: while square112 != diceRoll112 {
diceRoll112 += 1
if diceRoll112 == 7 { diceRoll112 = 1 }
switch square112 + diceRoll112 {
case finalSquare112:
// diceRoll will move us to the final square, so the game is over
break gameLoop
case let newSquare where newSquare > finalSquare:
// diceRoll will move us beyond the final square, so roll again
continue gameLoop
default:
// this is a valid move, so find out its effect
square112 += diceRoll112
square112 += board112[square112]
}
}
print("112 Game over!")
// 在这个代码中,将游戏的循环命名为gameLoop,然后在每一步移动格子时,判断当前是否到达了游戏终点,在break的时候,需要将整个游戏循环终止掉,而不是终止switch,因此用到了break gameLoop。同样的,在第二个分支中,continue gameLoop也指明了需要continue的是整个游戏,而不是switch语句本身。