http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 3425|回复: 4

[Swift] 【Swift基础教程】控制流-控制转移语句(Control Transfer Statements)

[复制链接]
发表于 2019-1-7 17:27:51 | 显示全部楼层 |阅读模式


    导读

【Swift基础教程】目录   http://www.sufeinet.com/thread-24641-1-1.html


控制转移语句


控制转移语句改变你代码的执行顺序,通过它可以实现代码的跳转。Swift 有五种控制转移语句

  • continue
  • break
  • fallthrough
  • return
  • throw


我们将会在下面讨论continue、break和fallthrough语句。return语句将会在函数章节讨论,throw语句会在错误抛出章节讨论。

Continue

continue语句告诉一个循环体立刻停止本次循环,重新开始下次循环。就好像在说“本次循环我已经执行完了”,但是并不会离开整个循环体。

下面的例子把一个小写字符串中的元音字母和空格字符移除,生成了一个含义模糊的短句:

let puzzleInput = "great minds think alike"
var puzzleOutput = ""
for character in puzzleInput {
    switch character {
    case "a", "e", "i", "o", "u", " ":
        continue
    default:
        puzzleOutput.append(character)
    }
}
print(puzzleOutput)

// 输出 "grtmndsthnklk"


在上面的代码中,只要匹配到元音字母或者空格字符,就调用continue语句,使本次循环结束,重新开始下次循环。这种行为使switch匹配到元音字母和空格字符时不做处理,而不是让每一个匹配到的字符都被打印。

Break

break语句会立刻结束整个控制流的执行。break 可以在 switch 或循环语句中使用,用来提前结束switch或循环语句。

循环语句中的 break
当在一个循环体中使用break时,会立刻中断该循环体的执行,然后跳转到表示循环体结束的大括号(})后的第一行代码。不会再有本次循环的代码被执行,也不会再有下次的循环产生。

Switch 语句中的 break

当在一个switch代码块中使用break时,会立即中断该switch代码块的执行,并且跳转到表示switch代码块结束的大括号(})后的第一行代码。

这种特性可以被用来匹配或者忽略一个或多个分支。因为 Swift 的switch需要包含所有的分支而且不允许有为空的分支,有时为了使你的意图更明显,需要特意匹配或者忽略某个分支。那么当你想忽略某个分支时,可以在该分支内写上break语句。当那个分支被匹配到时,分支内的break语句立即结束switch代码块。

注意: 当一个switch分支仅仅包含注释时,会被报编译时错误。注释不是代码语句而且也不能让switch分支达到被忽略的效果。你应该使用break来忽略某个分支。

下面的例子通过switch来判断一个Character值是否代表下面四种语言之一。为了简洁,多个值被包含在了同一个分支情况中。

let numberSymbol: Character = "三"  // 简体中文里的数字 3
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).")
}
// 输出 "The integer value of 三 is 3."


这个例子检查numberSymbol是否是拉丁,阿拉伯,中文或者泰语中的1到4之一。如果被匹配到,该switch分支语句给Int?类型变量possibleIntegerValue设置一个整数值。

当switch代码块执行完后,接下来的代码通过使用可选绑定来判断possibleIntegerValue是否曾经被设置过值。因为是可选类型的缘故,possibleIntegerValue有一个隐式的初始值nil,所以仅仅当possibleIntegerValue曾被switch代码块的前四个分支中的某个设置过一个值时,可选的绑定才会被判定为成功。

在上面的例子中,想要把Character所有的的可能性都枚举出来是不现实的,所以使用default分支来包含所有上面没有匹配到字符的情况。由于这个default分支不需要执行任何动作,所以它只写了一条break语句。一旦落入到default分支中后,break语句就完成了该分支的所有代码操作,代码继续向下,开始执行if let语句。

贯穿

在 Swift 里,switch语句不会从上一个 case 分支跳转到下一个 case 分支中。相反,只要第一个匹配到的 case 分支完成了它需要执行的语句,整个switch代码块完成了它的执行。相比之下,C 语言要求你显式地插入break语句到每个 case 分支的末尾来阻止自动落入到下一个 case 分支中。Swift 的这种避免默认落入到下一个分支中的特性意味着它的switch 功能要比 C 语言的更加清晰和可预测,可以避免无意识地执行多个 case 分支从而引发的错误。

如果你确实需要 C 风格的贯穿的特性,你可以在每个需要该特性的 case 分支中使用fallthrough关键字。下面的例子使用fallthrough来创建一个数字的描述语句。

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)
// 输出 "The number 5 is a prime number, and also an integer."


这个例子定义了一个String类型的变量description并且给它设置了一个初始值。函数使用switch逻辑来判断integerToDescribe变量的值。当integerToDescribe的值属于列表中的质数之一时,该函数在description后添加一段文字,来表明这个数字是一个质数。然后它使用fallthrough关键字来“贯穿”到default分支中。default分支在description的最后添加一段额外的文字,至此switch代码块执行完了。

如果integerToDescribe的值不属于列表中的任何质数,那么它不会匹配到第一个switch分支。而这里没有其他特别的分支情况,所以integerToDescribe匹配到default分支中。

当switch代码块执行完后,使用print(_:separator:terminator函数打印该数字的描述。在这个例子中,数字5被准确的识别为了一个质数。

注意: fallthrough关键字不会检查它下一个将会落入执行的 case 中的匹配条件。fallthrough简单地使代码继续连接到下一个 case 中的代码,这和 C 语言标准中的switch语句特性是一样的。

带标签的语句

在 Swift 中,你可以在循环体和条件语句中嵌套循环体和条件语句来创造复杂的控制流结构。并且,循环体和条件语句都可以使用break语句来提前结束整个代码块。因此,显式地指明break语句想要终止的是哪个循环体或者条件语句,会很有用。类似地,如果你有许多嵌套的循环体,显式指明continue语句想要影响哪一个循环体也会非常有用。

为了实现这个目的,你可以使用标签(statement label)来标记一个循环体或者条件语句,对于一个条件语句,你可以使用break加标签的方式,来结束这个被标记的语句。对于一个循环语句,你可以使用break或者continue加标签,来结束或者继续这条被标记语句的执行。

声明一个带标签的语句是通过在该语句的关键词的同一行前面放置一个标签,作为这个语句的前导关键字(introducor keyword),并且该标签后面跟随一个冒号。下面是一个针对while循环体的标签语法,同样的规则适用于所有的循环体和条件语句。

label name: while condition {
    statements
}

下面的例子是前面章节中蛇和梯子的适配版本,在此版本中,我们将使用一个带有标签的while循环体中调用break和continue语句。这次,游戏增加了一条额外的规则:

为了获胜,你必须刚好落在第 25 个方块中。
如果某次掷骰子使你的移动超出第 25 个方块,你必须重新掷骰子,直到你掷出的骰子数刚好使你能落在第 25 个方块中。

游戏的棋盘和之前一样:

finalSquare、board、square和diceRoll值被和之前一样的方式初始化:

let finalSquare = 25
var board = [Int](repeating: 0, 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循环和switch语句来实现游戏的逻辑。while循环有一个标签名gameLoop,来表明它是游戏的主循环。

该while循环体的条件判断语句是while square !=finalSquare,这表明你必须刚好落在方格25中。

gameLoop: while square != finalSquare {
    diceRoll += 1
    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]
    }
}
print("Game over!")

每次循环迭代开始时掷骰子。与之前玩家掷完骰子就立即移动不同,这里使用了switch语句来考虑每次移动可能产生的结果,从而决定玩家本次是否能够移动。

如果骰子数刚好使玩家移动到最终的方格里,游戏结束。break gameLoop语句跳转控制去执行while循环体后的第一行代码,意味着游戏结束。
如果骰子数将会使玩家的移动超出最后的方格,那么这种移动是不合法的,玩家需要重新掷骰子。continue gameLoop语句结束本次while循环,开始下一次循环。
在剩余的所有情况中,骰子数产生的都是合法的移动。玩家向前移动 diceRoll 个方格,然后游戏逻辑再处理玩家当前是否处于蛇头或者梯子的底部。接着本次循环结束,控制跳转到while循环体的条件判断语句处,再决定是否需要继续执行下次循环。

注意:
如果上述的break语句没有使用gameLoop标签,那么它将会中断switch语句而不是while循环。使用gameLoop标签清晰的表明了break想要中断的是哪个代码块。 同时请注意,当调用continue gameLoop去跳转到下一次循环迭代时,这里使用gameLoop标签并不是严格必须的。因为在这个游戏中,只有一个循环体,所以continue语句会影响到哪个循环体是没有歧义的。然而,continue语句使用gameLoop标签也是没有危害的。这样做符合标签的使用规则,同时参照旁边的break gameLoop,能够使游戏的逻辑更加清晰和易于理解。





1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2019-1-7 17:28:28 | 显示全部楼层
强烈支持楼主ing……
发表于 2019-1-7 17:28:51 | 显示全部楼层
我只是路过打酱油的。
发表于 2019-1-7 17:45:35 | 显示全部楼层
强烈支持楼主ing……
发表于 2019-1-7 20:50:29 | 显示全部楼层
看到这帖子真是高兴!
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-5-8 21:14

© 2014-2021

快速回复 返回顶部 返回列表