美文网首页
Swift5-外行零基础入门_9-控制流

Swift5-外行零基础入门_9-控制流

作者: DavidShawn | 来源:发表于2020-12-22 19:24 被阅读0次

    控制流

    什么是控制流?

    所谓控制流,是用来控制一件事物的流程的。跟数据类型一样,同样是模拟我们大脑对现实生活的处理模式。
    还记得我在开始举的例子的吗?一起来回顾一下:

    早晨起(床),吃完(早餐),出门穿上(外套),花(两元钱)买了公交(车票),到公司开始(干活)。

    我们的大脑能够轻松处理不同的数据类型,并且,我们实际上还在处理流程控制。让我们将上面这个例子细分一下:

    • 当我吃早饭时,只要没吃完,我就会一直吃,直到吃完或者吃饱;
    • 出门的时候检查有没有穿外套,穿了外套再出门;
    • 等公交车时,一辆接一辆,到了我要等的22路公交车,我就上车。
    • 如果我赶上了公交车,我就会到公司干活;

    看吧,这里隐藏了相当多的条件或循环。只有通过这种流程控制,我们才能自由处理各个对象。我们的大脑相当强大,强大到你根本不需要费劲思考,这些事情就顺理成章的完成了。
    再说回可怜的计算机,它需要你给他交待具体的任务安排。就像家长给上小学的孩子辅导作业一样,你需要把自己的认知也暂时拉低到小学水平,这样你才能给孩子讲明白题目。

    有哪些控制流?

    明白了什么是控制流,我们再来看看,Swift能接受哪些具体的命令来组织事务的控制流程:

    • for-in 循环:多用在数据组合中,对单个数据进行逐项遍历;
    • While 循环:如果某个条件满足,就一直循环,直到条件不满足;
    • if 条件语句:如果某个条件满足,就做某件事,否则就做另一件事;
    • Switch 匹配语句:列举很多条件,满足其中某个条件时,做某件事。
      上面,只是简略的阐述了每个语句的意思,实际运用时,有很多细节需要注意,我们逐条来看一下。

    1. for-in 循环

    for-in循环有点像是做上楼梯(每个台阶踩一遍)点名(每个人都要点一遍)这种比较机械的工作。

    • 基本用法
      for-in循环我们之前已经多次用过了,在遍历数组,集合,字典中的值时,经常用到。
    var arrayNumbers = [1,2,3]
    for i in arrayNumbers {
        print(i)
    }
    // 1,2,3
    
    • 遍历区间
      我们之前提到过区间,比如1...6,就是1,2,3,4,5,6这几个数字,也是可以用for in进行遍历的。
    for i in 1...6 {
        print(i)
    }
    // 1,2,3,4,5,6
    

    在这个例子中,i是1-6范围的值,每一步都取了一次当前值,并打印出来。
    我们还可以仅仅执行这段循环,而不打印出i

    for i in 1...6 {
        print("Hello")
    }
    // 打印了六遍"Hello"
    

    在这个例子中,我们并没有在后面使用i,因此,我们可以用_代替i

    for _ in 1...6 {
        print("Hello")
    }
    // 同样打印了六遍"Hello"
    
    • 步进遍历
      上楼梯的时候,我可以两步两步上;也可以从二楼开始上(也许是坐电梯到的二楼?)。总之,有选择的可能。
      这时,我们可以使用stride(from:to:by:)或者是stride(from:through:by:),先看下面的例子:
    for i in stride(from:2, to: 100, by: 5) {
        print(i)
    }
    // 请自己在Playground中试一下结果。
    

    这段代码实现了更加多的参数,在100这个范围内,从2开始数,每隔5数一次。

    2. While 循环

    while condition {
        statements
    }
    

    如果说for in做的工作比较机械的话,while,if,switch就比较有目的性了,我们先看while

    • 基本用法
      首先看一个示例,我会持续吃,直到我感觉有差不多八成饱。这段描述可以用代码来表达:
    var 饱腹感 = 1
    while 饱腹感 < 8 {
        print("再吃一口……")
        饱腹感 += 1
    }
    

    分析这段代码:
    首先,我很饿,用变量表示var 饱腹感 = 1,我给自己设定的条件是要吃到八成饱,饱腹感 < 8这实际上是一个判断,得出的就是一个判断值,也就是布尔值,是true or false
    开始饱腹感是1,满足了饱腹感 < 8这个判断,就会执行while包起来的语句,我会再吃一口饱腹感就会加1。这时,代码运行完了,再从头运行,再次判断饱腹感的值,直到饱腹感=8的时候,条件就不满足了,就停止执行。
    代码停止了,但是代码运行了7次再吃一口,也达到了目的。

    • 类比:
      for-in也能实现类似的多次执行的效果,但是while更接近自然语言,可以类比中文当……时,就……。在合适的情况下使用,代码的可读性就会更好。
      这有点像上学的时候,老师给我们批改作文,会说你这里用词不当。怎么才能用词恰当呢?就需要多读,多写,慢慢进步。等到你成年后,你就不太会说:我已经饱的无与伦比了,这样用词不当的话了。

    • repeat-while

    repeat {
        statements
    } while condition
    

    理解了while的基本用法后,这里就很好理解。repeat-whilewhile的最大区别就是,无论什么条件,先执行一段代码。用我们的例子说明,就是管他饿不饿,先吃一口。上面的代码可以改为:

    var 饱腹感 = 8
    repeat {
        print("再吃一口……")
        饱腹感 += 1
    }
    while 饱腹感 < 8
    

    这里,我把饱腹感的初始值设为8,虽然达到我的八成饱要求了,可是还要首先吃一口再说。

    3. if 条件语句

    if条件语句的意思是如果……就……,如果某个条件满足,就执行某个动作。一个萝卜一个坑,对预期控制的比较精确,也是编程语言中最常用的逻辑控制语句。

    • 基本用法
    if condition {
        statements
    }
    

    condition同样是一个布尔值,statements是某个动作。
    举个与生活相关的例子,如果天气晴朗,我就出门,用代码可以表示:

    var 天气 = "晴朗"
    if 天气 == "晴朗" {
        print("我要出门")
    }
    

    声明一下,为了便于理解,我们使用了中文名称作为变量,swift也能正常执行,但是在正式开发中,尽量避免这样使用。我能想到的最大缺点就是,这样做会影响兼容性,因为其他大部分人都不这么干。
    上面这段代码,if的条件是成立的,因此会执行print()语句,如果你把天气的值改为其他,print()就不会执行了。

    • if else
      既然是假设,那么我们还会有更复杂的情况,比如,如果天气晴朗,我就出门。如果阴天、下雨、大风等坏天气,我就在家上网。这段描述,可以用代码表示如下:
    var 天气 = "下雨"
    if 天气 == "晴朗" {
        print("我要出门")
    } else {
        print("在家上网")
    }
    

    这里,加了else的意思是,除了天气 == "晴朗"这个条件,其他任何情况下,执行的动作。
    满足一个条件,执行一个命令。如果不满足这个条件,就执行另一个命令。

    • if else if else
      如果有多项判断,可以使用else if。在上面的例子中,我们可以细化对不同情况的反应。比如,如果天气晴朗,我就出门;如果下雨,我就带伞出门;否则,我就在家上网。
    var 天气 = "下雨"
    if 天气 == "晴朗" {
        print("我要出门")
    } else if 天气 == "下雨" {
        print("带伞出门")
    } else {
        print("在家上网")
    }
    

    还有一种跟if条件很类似的 guard语句,主要在函数中使用,我们后面再说。

    4. Switch 匹配语句

    • 基本用法
      如果有多项条件,每个条件都各自对应一种动作时,除了用多个else if之外,还可以使用switch语句。
    var 天气 = "晴朗"
    switch 天气 {
    case "晴朗":
        print("出门遛弯。")
    case "下雨":
        print("出门带伞。")
    default:
        print("在家上网。")
    }
    

    有没有发现switchif的最大区别?if后面的条件是布尔值,而switch后面是具体的数据,case后面的值也是从具体的数据中做选择。这样就灵活了很多。
    但是要注意,case是顺序执行,一旦满足,后面就不再执行了。

    • 复合匹配
      因此,我们可以轻松使用复合数据进行匹配
    var 天气 = "阴天"
    switch 天气 {
    case "晴朗", "阴天":
        print("出门遛弯。")
    case "下雨":
        print("出门带伞。")
    default:
        print("在家上网。")
    }
    

    我在第一行case中同时列举了两个条件,阴天也能出门遛弯。如果是用if,你需要这样列举天气=="晴朗" || 天气=="阴天",因为if后面只能跟布尔值。

    • 区间匹配
      非布尔值带来的好处,还可以使用区间。举个另外的我们经常用的评分例子:
    var 分数 = 86
    switch 分数 {
    case 0...60:
        print("不及格")
    case 61...80:
        print("良好")
    case 81...100:
        print("优秀")
    default:
        print("分数有误")
    }
    
    • 元组匹配
      switch还能按元组匹配,也很使用,看下面这个例子:
    var 生命 = 90
    var 魔法 = 86
    
    switch (生命, 魔法) {
    case (100, 100):
        print("英雄的状态完美!")
    case (_, 30...100):
        print("可以释放魔法!")
    case (0..<30, _):
        print("生命值低,危险!")
    default:
        print("分数有误")
    }
    

    从这个例子,可以看到元组匹配的特性:能按元组精确匹配,使用_可以忽略某项匹配,可以按区间匹配。

    • 值绑定
      我们可以在case分支中,用常量或变量绑定条件中的值,这样,方便在该分支中,继续操作数据。
    var status = (30,60)
    switch status {
    case let (生命, 魔法):
        print("生命值:\(生命), 魔法值:\(魔法)")
        let 状态值 = 生命 + 魔法
        print("\(状态值)")
    }
    

    还可以配合where, 进行条件判断。会让绑定值显得更有意义。

    var status = (30,60)
    switch status {
    case let (生命, 魔法) where 生命 + 魔法 > 100:
        print("可以释放魔法!")
    case let (生命, 魔法):
        print("生命值:\(生命), 魔法值:\(魔法)")
        let 状态值 = 生命 + 魔法
        print("状态值(\(状态值))不够,不能释放魔法。")
    
    }
    

    调整状态值,能得到不同case执行动作,你可以在Playground中多试试。

    7. 控制转移语句

    最后,我们来简单介绍几条控制语句.
    continuebreakfallthroughreturnthrow
    return多用在函数中,throw多用在错误处理中,我们也放在后面介绍。
    continuebreakfallthrough这几个语句主要用在前面所说的各种循环语句中,因为有时候这些循环的默认执行状态并不能满足需求,这时候,可以搭配这些语句,来控制流程的走向。
    下面只是举了部分例子,先想象结果如何,然后在Playground中验证试试,也可以按自己的想法修改、调试:

    • continue
    var 天气 = ["晴朗","雷暴","阴天","下雨"]
    for i in 天气 {
        if i == "雷暴" {
            continue
        } else {
            print("\(i)可以出门")
        }
    }
    

    在遍历循环的时候,如果遇到“雷暴”,用continue跳过,不做任何事情。

    • break
    var 天气 = ["晴朗","阴天","下雨","雷暴","台风"]
    for i in 天气 {
        if i == "雷暴" {
            break
        } else {
            print("\(i)可以出门")
        }
    }
    

    在遍历的过程中,遇到“雷暴”,整条循环就停止了,后面就不会继续判断了。

    • fallthrough
    var 天气 = ["晴朗","阴天","下雨","雷暴","台风"]
    for i in 天气 {
        switch i {
        case "晴朗":
            print("可以出门")
        case "阴天":
    //        print("可以出门")
            fallthrough
        case "下雨":
            print("带伞出门")
        default:
            print("在家上网!")
        }
    }
    

    在本段代码中,fallthrough使本段代码直接交给下一条case处理。使得“阴天”这条case也会打印“带伞出门。”

    小结与预告

    掌握了流程控制,我们就可以对数据进行操控了。编程的本质,无非是一系列的假设,判断,循环等等。
    我们可以利用已经学到的知识,写很多东西了。比如,

    • 根据圆的半径,求圆面积;
    • 已知一个班10个同学的成绩,根据他们的分数进行不及格,良,优的评级;
    • 已知一位英雄的生命值和魔法值,每释放一次魔法,就消耗10点生命和60点魔法,直到某一个值不能满足最低的安全值。
      这是三个例子,证明你根据已有知识,是能够写出这样的程序的,哪怕简单一些。
      这也是三个作业,没有标准答案,你试着独立写一写,对我们学习下一节很有帮助。

    来点小提示:

    1. 算术运算符处理数字
    2. if或switch判断分数的范围
    3. 用while循环包住一个if判断,在其中进行变量的增减操作

    相关文章

      网友评论

          本文标题:Swift5-外行零基础入门_9-控制流

          本文链接:https://www.haomeiwen.com/subject/kewwiktx.html