Skip to content

第6天 循环

循环是让计算机如此出色的原因之一:它能够每秒重复执行某些简单任务数十亿次。

当然,循环中具体执行什么任务取决于你:你可能在累加一些数字,可能在读取一些传感器数据,或者可能在每秒重绘屏幕 120 次。正如克雷格・布鲁斯所说:“硬件让机器变快,但软件却可能让快的机器变慢。”

今天你需要完成三个教程,此外还有一个总结和一个 检查练习。 完成每个视频后,你可以阅读可选的额外部分,还有一个简短的测试来帮助你确认是否理解了所教授的内容。

6.1 如何使用 for 循环重复执行任务

作者:Paul Hudson 2021 年 10 月 25 日 已针对 Xcode 16.4 更新

计算机非常擅长执行重复性工作,而 Swift 让重复执行一段代码变得很简单,无论是固定次数,还是为数组、字典或集合中的每个元素执行一次。

让我们从简单的例子开始:如果我们有一个字符串数组,我们可以像这样打印出每个字符串:

swift
let platforms = ["iOS", "macOS", "tvOS", "watchOS"]

for os in platforms {
    print("Swift 在 \(os) 上表现很棒。")
}

这段代码会遍历 platforms 中的所有元素,逐个将它们放入 os 中。我们没有在其他地方创建 os;它是作为循环的一部分创建的,并且只在花括号内部可用。

花括号内部是我们希望为数组中的每个元素执行的代码,所以上面的代码会打印四行 —— 每个循环元素对应一行。首先,它会把 “iOS” 放入 os 中,然后调用 print(),接着把 “macOS” 放入 os 中并调用 print(),之后是 “tvOS”,再之后是 “watchOS”。

为了便于理解,我们给这些东西起了常见的名称:

  • 我们把花括号内部的代码称为循环体
  • 我们把执行一次循环体称为一次循环迭代
  • 我们把 os 称为循环变量。它只存在于循环体内部,并且会在下一次循环迭代中变为新值。

需要说明的是,os 这个名称并没有什么特别之处 —— 我们也可以这样写:

swift
for name in platforms {
    print("Swift 在 \(name) 上表现很棒。")
}

甚至可以这样写:

swift
for rubberChicken in platforms {
    print("Swift 在 \(rubberChicken) 上表现很棒。")
}

代码的运行效果还是完全一样的。

实际上,Xcode 在这方面很智能:如果你写 for plat,它会识别出有一个名为 platforms 的数组,并会提示自动补全为 for platform in platforms—— 它能识别出 platforms 是复数形式,并为循环变量建议单数形式的名称。当你看到 Xcode 出现这个建议时,按回车键选择它即可。

除了遍历数组(或集合、字典 —— 语法是一样的!),你也可以遍历一个固定的数字范围。例如,我们可以像这样打印出 5 乘以 1 到 12 的乘法表:

swift
for i in 1...12 {
    print("5 乘以 \(i) 等于 \(5 * i)")
}

这里有几个新知识点,我们停下来仔细看看:

  • 我使用了循环变量 i,这是一个常见的编码约定,表示 “用于计数的数字”。如果你要数第二个数字,可以用 j,数第三个可以用 k,但如果要数第四个,或许你应该选择更好的变量名。
  • 1...12 这部分是一个范围,意思是 “从 1 到 12 之间的所有整数,包括 1 和 12 本身”。范围在 Swift 中是一种独特的数据类型。

所以,当循环第一次运行时,i 是 1,然后是 2,接着是 3,以此类推,一直到 12,之后循环就结束了。

你也可以把循环放在另一个循环里面,这称为嵌套循环,就像这样:

swift
for i in 1...12 {
    print("\(i) 的乘法表:")

    for j in 1...12 {
        print("  \(j) 乘以 \(i) 等于 \(j * i)")
    }

    print()
}

这里又展示了一些新东西,我们再停下来仔细看看:

  • 现在有一个嵌套循环:我们从 1 数到 12,对于其中的每个数字,我们再从 1 数到 12 一次。
  • 单独使用 print(),不传入任何文本或值,只会开始一个新的行。这有助于分隔我们的输出,使它在屏幕上看起来更美观。

所以,当你看到 x...y 时,就知道它创建了一个范围,从数字 x 开始,一直数到并包括数字 y

Swift 有一种类似但又不同的范围类型,它数到但不包括最后一个数字:..<。在代码中看会更清楚:

swift
for i in 1...5 {
    print("从 1 数到 5(包含 5):\(i)")
}

print()

for i in 1..<5 {
    print("从 1 数到 5(不包含 5):\(i)")
}

运行这段代码时,第一个循环会打印数字 1、2、3、4、5,而第二个循环只会打印数字 1、2、3、4。我把 1...5 读作 “1 到 5(包含 5)”,把 1..<5 读作 “1 到 5(不包含 5)”,在 Swift 中你也会看到类似的表述。

提示: ..< 在处理数组时非常有用,因为数组的索引从 0 开始,而且我们经常需要数到但不包括数组的元素个数。

在结束关于 for 循环的讨论之前,还有一件事我想提一下:有时候你想用一个范围来运行一段代码特定的次数,但实际上你并不需要循环变量 —— 你不需要 ij,因为你用不到它们。

在这种情况下,你可以用下划线替换循环变量,像这样:

swift
var lyric = "Haters gonna"

for _ in 1...5 {
    lyric += " hate"
}

print(lyric)

(没错,这是泰勒・斯威夫特《Shake It Off》中的一句歌词,用 Swift 代码写出来了。)

【可选阅读】为什么 Swift 在循环中使用下划线?

作者:Paul Hudson 2021 年 10 月 25 日 已针对 Xcode 16.4 更新

如果你想遍历数组中的元素,你可能会写出这样的代码:

swift
let names = ["Sterling", "Cyril", "Lana", "Ray", "Pam"]

for name in names {
    print("\(name) 是一名特工")
}

每次循环运行时,Swift 会从 names 数组中取出一个元素,把它放入 name 常量中,然后执行我们的循环体 —— 也就是 print() 方法。

然而,有时候你实际上并不需要当前正在读取的值,这时候就用到下划线了:Swift 会识别出你并不需要这个变量,就不会为你创建这个临时常量了。

当然,Swift 本身也能察觉到这一点 —— 它能看到你是否在循环体中使用了 name,所以即使没有下划线,它也能完成同样的工作。不过,使用下划线对我们理解代码也有类似的帮助:无论循环体中有多少行代码,我们一看代码就能立刻知道循环变量没有被使用。

所以,如果你在循环体中没有使用循环变量,Swift 会警告你把代码改写成这样:

swift
let names = ["Sterling", "Cyril", "Lana", "Ray", "Pam"]

for _ in names {
    print("[已审查] 是一名特工!")
}

【可选阅读】为什么 Swift 有两种范围运算符?

作者:Paul Hudson 2020 年 5 月 28 日 已针对 Xcode 16.4 更新

当我们想到值的范围时,英语的表述很容易让人混淆。如果我说 “给我截至昨天的销售数据”,这是指包含昨天还是不包含昨天呢?这两种情况都有各自的用途,所以 Swift 给我们提供了两种表示方式:..< 是半开范围运算符,表示 “到但不包含”,... 是闭范围运算符,表示 “到且包含”。

为了在谈论时更容易区分,Swift 经常使用非常明确的语言:“1 到 5(up to 5)” 指的是 1、2、3、4,而 “1 到 5(through 5)” 指的是 1、2、3、4、5。你要记住,Swift 的数组索引从 0 开始,这意味着一个包含 3 个元素的数组,其元素的索引分别是 0、1、2—— 这是半开范围运算符的完美用例。

当你只想要范围的一部分时,情况会更有趣,比如 “从 0 开始的所有数” 或者 “从索引 5 到数组末尾”。你知道,这些在编程中是相当有用的,所以 Swift 让我们可以只指定范围的一部分来轻松创建它们。

例如,如果我们有一个像这样的名字数组:

swift
let names = ["Piper", "Alex", "Suzanne", "Gloria"]

我们可以像这样读取一个单独的名字:

swift
print(names[0])

有了范围,我们也可以像这样打印一个范围的值:

swift
print(names[1...3])

不过,这有一个小风险:如果我们的数组至少没有 4 个元素,那么 1...3 就会出错。幸运的是,我们可以使用单侧范围来表示 “给我从 1 到数组末尾的元素”,像这样:

swift
print(names[1...])

所以,范围不仅非常适合遍历特定的值,而且对于从数组中读取一组元素也很有帮助。

【练习题】for 循环

问题 1/12:这段代码会打印三行文本 —— 对还是错?

swift
for _ in 0...3 {
	print("Hip hip hurray!")
}

问题 2/12:这段代码会打印三行文本 —— 对还是错?

swift
let count = 1...3
for _ in count {
	print("There's no place like home.")
}

问题 3/12:这段代码会打印三行文本 —— 对还是错?

swift
for i in 4...6 {
	print("Star Wars: Episode \(i)")
}

问题 4/12:这段代码会打印三行文本 —— 对还是错?

swift
for beatle in "John", "Paul", "Ringo" {
	print("\(beatle) was in the Beatles")
}

问题 5/12:这段代码会打印三行文本 —— 对还是错?

swift
let albums = ["1989", "Red"]
for album in albums {
	print("\(album) was a great album!")
}

问题 6/12:这段代码会打印三行文本 —— 对还是错?

swift
var names = ["John", "Sophie", "Lottie"]
for name in names {
	print("Hello, \(name)!")
}

问题 7/12:这段代码会打印三行文本 —— 对还是错?

swift
var numbers = [1, 2, 3, 4, 5, 6]
for number in numbers {
	if number.isMultiple(of: 2) {
		print(number)
	}
}

问题 8/12:这段代码会打印三行文本 —— 对还是错?

swift
print("Haters gonna ")
for _ in 1...4 {
	print("hate")
}

问题 9/12:这段代码会打印三行文本 —— 对还是错?

swift
for number in [2, 3, 5] {
	print("\(number) is a prime number.")
}

问题 10/12:这段代码会打印三行文本 —— 对还是错?

swift
let score = 100
for count in 10..<13 {
	print("I'm counting to \(count)")
}

问题 11/12:这段代码会打印三行文本 —— 对还是错?

swift
for i in 1...8 {
	if i < 3 {
		print("\(i) is a small number")
	}
}

问题 12/12:这段代码会打印三行文本 —— 对还是错?

swift
var speeds = (65, 58, 72)
for speed in speeds {
	print("You were driving at \(speed)km/h.")
}

6.2 如何使用 while 循环重复执行任务

作者:Paul Hudson 2021 年 10 月 25 日 已针对 Xcode 16.4 更新

Swift 有一种名为 while 的第二种循环:给它一个条件,while 循环就会持续执行循环体,直到条件为假。

虽然你偶尔还是会看到 while 循环,但它们不像 for 循环那样常见。因此,我想介绍一下它们,让你知道它们的存在,但我们就不细说了,好吗?

下面是一个基本的 while 循环示例,让我们开始了解:

swift
var countdown = 10

while countdown > 0 {
    print("\(countdown)…")
    countdown -= 1
}

print("发射!")

这段代码创建了一个从 10 开始的整数计数器,然后启动了一个条件为 countdown > 0while 循环。所以,循环体(打印数字并减 1)会持续运行,直到 countdown 等于或小于 0,这时循环会结束,然后打印最后的消息。

当你不知道循环要执行多少次时,while 循环非常有用。为了说明这一点,我想向你介绍 IntDouble 都具有的一个非常实用的功能:random(in:)。给它一个数字范围,它会返回该范围内的一个随机 IntDouble

例如,下面的代码会创建一个 1 到 1000 之间的新整数:

swift
let id = Int.random(in: 1...1000)

而这段代码会创建一个 0 到 1 之间的随机小数:

swift
let amount = Double.random(in: 0...1)

我们可以将这个功能与 while 循环结合起来,一次又一次地掷虚拟的 20 面骰子,直到掷出 20 点才结束循环 —— 对于所有《龙与地下城》玩家来说,这可是一次暴击哦。

实现这个功能的代码如下:

swift
// 创建一个整数来存储我们的掷骰结果
var roll = 0

// 继续循环,直到我们掷出 20 点
while roll != 20 {
    // 掷一个新的骰子并打印结果
    roll = Int.random(in: 1...20)
    print("我掷出了 \(roll) 点")
}

// 如果我们到了这里,说明循环结束了——我们掷出了 20 点!
print("暴击!")

在你自己的代码中,你会用到 for 循环和 while 循环:for 循环在有有限的数据需要处理时更常见,比如一个范围或一个数组,而 while 循环在你需要自定义条件时非常有用。

【可选阅读】什么时候应该使用 while 循环?

作者:Paul Hudson 2020 年 5 月 28 日 已针对 Xcode 16.4 更新

Swift 提供了 for 循环和 while 循环,两者都很常用。然而,当你刚开始学习时,有两种常用的循环方式可能会让你觉得奇怪 —— 你应该用哪一种,为什么呢?

主要区别在于,for 循环通常用于有限的序列:例如,我们遍历 1 到 10 的数字,或者数组中的元素。另一方面,while 循环可以循环到任何任意条件为假时为止,这使得它们可以一直循环到我们让它们停止的时候。

这意味着我们可以重复执行相同的代码,直到:

  • …… 用户要求我们停止
  • …… 服务器让我们停止
  • …… 我们找到了我们要找的答案
  • …… 我们生成了足够的数据

这些只是几个例子。想想看:如果我让你掷 10 次骰子并打印结果,你可以用一个简单的 for 循环从 1 数到 10 来实现。但是如果我让你掷 10 次骰子并打印结果,同时如果前一次骰子的结果相同,就自动再掷一次,那么你事先并不知道需要掷多少次骰子。也许你运气好,只需要掷 10 次,但也许你会有几次重复的结果,需要掷 15 次。或者可能你有很多次重复的结果,需要掷 30 次 —— 谁知道呢?

这就是 while 循环派上用场的地方:我们可以让循环一直运行,直到我们准备好退出为止。

【练习题】while 循环

问题 1/12:这个循环会打印五行文本 —— 对还是错?

swift
while 0 < 5 {
	print("我在数到 5!")
}

问题 2/12:这个循环会打印五行文本 —— 对还是错?

swift
let colors = ["红色", "绿色", "蓝色", "橙色", "黄色"]
var colorCounter = 0
while colorCounter < 5 {
	print("\(colors[colorCounter]) 是一种受欢迎的颜色。")
	colorCounter += 1
}

问题 3/12:这个循环会打印五行文本 —— 对还是错?

swift
var counter = 2
while counter < 64 {
	print("\(counter) 是 2 的幂。")
	counter *= 2
}

问题 4/12:这个循环会打印五行文本 —— 对还是错?

swift
var page: Int = 0
while page <= 5 {
	page += 1
	print("我正在读第 \(page) 页。")
}

问题 5/12:这个循环会打印五行文本 —— 对还是错?

swift
var pianoLesson = 1
while pianoLesson < 5 {
	print("这是第 \(pianoLesson) 节课")
	pianoLesson += 1
}

问题 6/12:这个循环会打印五行文本 —— 对还是错?

swift
var cats: Int = 0
while cats < 10 {
	cats += 1
	print("我又养了一只猫。")
	if cats == 4 {
		print("猫够多了!")
		cats = 10
	}
}

问题 7/12:这个循环会打印五行文本 —— 对还是错?

swift
var itemsSold: Int = 0
while itemsSold < 5000 {
	itemsSold += 100
	if itemsSold.isMultiple(of: 10000) {
		print("售出 \(itemsSold) 件商品——一个重要的里程碑!")
	}
}

问题 8/12:这个循环会打印五行文本 —— 对还是错?

swift
var number: Int = 10
while number > 0 {
	number -= 2
	if number.isMultiple(of: 2) {
		print("\(number) 是一个偶数。")
	}
}

问题 9/12:这个循环会打印五行文本 —— 对还是错?

swift
let bottles = 10
while bottles > 0 {
	bottles -= 2
	print("\(bottles) 个绿色瓶子。")
}

问题 10/12:这个循环会打印五行文本 —— 对还是错?

swift
var position = 5
while position > 0 {
	print("\(position)!")
	position -= 1
}

问题 11/12:这个循环会打印五行文本 —— 对还是错?

swift
var averageScore = 2.5
while averageScore < 15.0 {
	averageScore += 2.5
	print("平均分数是 \(averageScore)")
}

问题 12/12:这个循环会打印五行文本 —— 对还是错?

swift
var speed = 50
while speed <= 55 {
	print("加速到 \(speed)")
	speed += 1
}

6.3 如何使用 break 和 continue 跳过循环项

作者:Paul Hudson 2021 年 10 月 5 日 已为 Xcode 16.4 更新

Swift 为我们提供了两种跳过循环中一个或多个项的方法:continue 跳过当前循环迭代,break 跳过所有剩余迭代。和 while 循环一样,它们有时会被用到,但实际上比你想象的要少得多。

让我们分别来看,先从 continue 开始。当你遍历一个数据数组时,Swift 会从数组中取出一个项,并使用它执行循环体。如果你在循环体内部调用 continue,Swift 会立即停止执行当前循环迭代,跳转到循环中的下一个项,然后像正常情况一样继续。这通常用在循环的开头,用于排除那些没有通过你设定的测试的循环变量。

下面是一个例子:

swift
let filenames = ["me.jpg", "work.txt", "sophie.jpg", "logo.psd"]

for filename in filenames {
    if filename.hasSuffix(".jpg") == false {
        continue
    }

    print("找到图片:\(filename)")
}

这段代码创建了一个文件名字符串数组,然后遍历每个文件名,检查它是否有后缀 “.jpg”—— 即它是否是一张图片。对于所有未通过该测试的文件名,都会使用 continue,这样循环体的其余部分就会被跳过。

至于 break,它会立即退出循环,并跳过所有剩余的迭代。为了演示这一点,我们可以编写一些代码来计算两个数字的 10 个公倍数:

swift
let number1 = 4
let number2 = 14
var multiples = [Int]()

for i in 1...100_000 {
    if i.isMultiple(of: number1) && i.isMultiple(of: number2) {
        multiples.append(i)

        if multiples.count == 10 {
            break
        }
    }
}

print(multiples)

它做了很多事情:

  1. 创建两个常量来存储两个数字。
  2. 创建一个整数数组变量,用于存储我们两个数字的公倍数。
  3. 从 1 数到 100,000,将每个循环变量赋给 i
  4. 如果 i 是第一个和第二个数字的公倍数,则将其添加到整数数组中。
  5. 一旦我们得到 10 个公倍数,就调用 break 退出循环。
  6. 打印结果数组。

所以,当你想跳过当前循环迭代的其余部分时使用 continue,当你想跳过所有剩余的循环迭代时使用 break

【可选阅读】为什么要退出循环?

作者:Paul Hudson 2020 年 6 月 5 日 已为 Xcode 16.4 更新

Swift 的 break 关键字让我们可以立即退出循环,无论我们谈论的是哪种循环。很多时候你不需要这个,因为你正在遍历数组中的项并想处理所有项,或者因为你要从 1 数到 10 并想处理所有这些值。

然而,有时你确实想提前结束循环。例如,如果你有一个分数数组,并且想知道玩家在得到 0 分之前获得了多少个分数,你可能会这样写:

swift
let scores = [1, 8, 4, 3, 0, 5, 2]
var count = 0

for score in scores {
    if score == 0 {
        break
    }

    count += 1
}

print("在得到 0 分之前,你有 \(count) 个分数。")

如果没有 break,我们需要在找到第一个 0 之后继续遍历分数,这很浪费。

【可选阅读】Swift 为什么有带标签的语句?

作者:Paul Hudson 2024 年 4 月 30 日 已为 Xcode 16.4 更新

Swift 的带标签语句允许我们为代码的某些部分命名,它最常用于跳出嵌套循环。

为了演示它们,让我们看一个例子,我们试图找出解锁保险箱的正确动作组合。我们可以先定义一个包含所有可能动作的数组:

swift
let options = ["上", "下", "左", "右"]

为了测试,下面是我们要猜测的秘密组合:

swift
let secretCombination = ["上", "上", "右"]

为了找到这个组合,我们需要生成包含所有可能的三个动作的数组:

  • 上、上、上
  • 上、上、下
  • 上、上、左
  • 上、上、右
  • 上、下、左
  • 上、下、右

…… 你懂的。

为了实现这一点,我们可以编写三个循环,一个嵌套在另一个里面,就像这样:

swift
for option1 in options {
    for option2 in options {
        for option3 in options {
            print("在循环中")
            let attempt = [option1, option2, option3]

            if attempt == secretCombination {
                print("组合是 \(attempt)!")
            }
        }
    }
}

这段代码多次遍历相同的项来创建一个 attempt 数组,如果它的尝试与秘密组合匹配,就会打印一条消息。

但这段代码有一个问题:一旦我们找到组合,循环就应该结束了,为什么它们还在继续运行呢?我们真正想说的是 “一旦找到组合,立即退出所有循环”—— 这就是带标签语句的用武之地。它们让我们可以这样写:

swift
outerLoop: for option1 in options {
    for option2 in options {
        for option3 in options {
            print("在循环中")
            let attempt = [option1, option2, option3]

            if attempt == secretCombination {
                print("组合是 \(attempt)!")
                break outerLoop
            }
        }
    }
}

有了这个小改动,一旦找到组合,这三个循环就会停止运行。在这个简单的例子中,它不太可能对性能产生影响,但如果你的项有数百甚至数千个呢?像这样节省工作量是个好主意,值得在你自己的代码中记住。

【可选阅读】何时使用 break 何时使用 continue

作者:Paul Hudson 2020 年 5 月 28 日 已为 Xcode 16.4 更新

有时 Swift 学习者很难理解何时使用 break 关键字,何时使用 continue 关键字,因为它们都会改变我们循环的流程。

当我们使用 continue 时,我们是在说 “我完成了这个循环的当前运行”——Swift 会跳过循环体的其余部分,然后转到循环中的下一个项。但当我们说 break 时,我们是在说 “我完全完成了这个循环,所以彻底退出吧”。这意味着 Swift 会跳过循环体的剩余部分,也会跳过所有其他尚未处理的循环项。

break 一样,你也可以将 continue 与带标签的语句一起使用,但说实话,我不记得见过这种用法!

【练习题】退出循环

问题 1/12:这个循环会打印一些文本 —— 对还是错?

swift
var isActive = false
while isActive {
	print("正在检查用户输入...")
}

问题 2/12:这个循环会打印一些文本 —— 对还是错?

swift
var counter = 0
while counter < 5 {
	counter += 1
	print("计数:\(counter)")
}

问题 3/12:这个循环会打印一些文本 —— 对还是错?

swift
for name in ["John", "Paul", "George"] {
	break
	print("欢迎,\(name)!")
}

问题 4/12:这个循环会打印一些文本 —— 对还是错?

swift
var password = "1"
while true {
	password += "1"
	if password == "11111" {
		print("这是一个很糟糕的密码。")
	}
	break
}

问题 5/12:这个循环会打印一些文本 —— 对还是错?

swift
repeat while true {
	print("正在获取更新")
}

问题 6/12:这个循环会打印一些文本 —— 对还是错?

swift
for i in 1...10 {
	if i == 8 {
		print("找到数字 8 了!")
	}
}

问题 7/12:这个循环会打印一些文本 —— 对还是错?

swift
var people = 2
while people < 10 {
	people += 2
	if people == 10 {
		print("我们有 10 个人了。")
	}
}

问题 8/12:这个循环会打印一些文本 —— 对还是错?

swift
for i in 1..<10 {
	if i == 10 {
		print("找到数字 10 了!")
	}
}

问题 9/12:这个循环会打印一些文本 —— 对还是错?

swift
while true {
	print("你好,世界!")
}

问题 10/12:这个循环会打印一些文本 —— 对还是错?

swift
for person in ["Taylor", "Justin", "Adele"] {
	print("你好,\(person)!")
}

问题 11/12:这个循环会打印一些文本 —— 对还是错?

swift
for i in 1...15 {
	if i.isMultiple(of: 3) {
		if i.isMultiple(of: 5) {
			print("\(i) 是 3 和 5 的公倍数。")
		}
	}
}

问题 12/12:这个循环会打印一些文本 —— 对还是错?

swift
var counter: Int = 1
while counter < 100 {
	counter += 10
	if counter.isMultiple(of: 10) {
		print("找到匹配的数字")
	}
}

6.4 总结:条件语句和循环

作者:Paul Hudson 2021 年 10 月 25 日 已更新至 Xcode 16.4 版本

在前几章中,我们已经学习了很多关于条件语句和循环的知识,现在来回顾一下:

  • 我们使用if语句来检查条件是否为真。你可以传入任何想要的条件,但最终它必须归结为一个布尔值。
  • 你可以根据需要添加else块,以及 / 或者多个else if块来检查其他条件。Swift 会按顺序执行这些块。
  • 你可以使用||组合条件,这意味着如果两个子条件中有一个为真,整个条件就为真;或者使用&&,这意味着只有两个子条件都为真时,整个条件才为真。
  • 如果你需要多次进行类似的检查,可以使用switch语句代替。switch语句必须涵盖所有可能的情况,这可能意味着需要添加一个默认情况。
  • 如果switch语句中的某个 case 使用了fallthrough,那么 Swift 会在执行完该 case 后继续执行下一个 case。这种用法并不常见。
  • 三元条件运算符让我们可以检查 WTF:What(判断条件)、True(条件为真时的结果)、False(条件为假时的结果)。虽然一开始可能有点难理解,但你会发现在 SwiftUI 中它的使用非常频繁。
  • for循环让我们可以遍历数组、集合、字典和范围。你可以将元素赋值给一个循环变量,并在循环内部使用它,或者可以使用下划线_来忽略循环变量。
  • while循环让我们可以创建自定义的循环,这些循环会一直运行,直到条件变为假。
  • 我们可以使用continue跳过某些循环项,或者使用break完全退出循环。

这又是一大块新内容,但有了条件语句和循环,你现在已经掌握了构建一些非常实用的软件所需的知识 —— 试试看吧!

6.5 检查点 3

作者:Paul Hudson 2021 年 10 月 5 日 已更新至 Xcode 16.4 版本

既然你已经能够使用条件语句和循环了,我想让你尝试一个经典的计算机科学问题。这个问题理解起来并不难,但根据你的过往经验,解决它可能需要一点时间!

这个问题叫做 “Fizz buzz”(嘶嘶嗡嗡),从我记事起,它就被用于求职面试、大学入学考试等等。你的目标是从 1 循环到 100,对于每个数字:

  1. 如果它是 3 的倍数,打印 “Fizz”
  2. 如果它是 5 的倍数,打印 “Buzz”
  3. 如果它既是 3 的倍数又是 5 的倍数,打印 “FizzBuzz”
  4. 否则,只需打印该数字。

所以,当你的代码运行时,应该会得到以下一些示例结果:

  • 1 应该打印 “1”
  • 2 应该打印 “2”
  • 3 应该打印 “Fizz”
  • 4 应该打印 “4”
  • 5 应该打印 “Buzz”
  • 6 应该打印 “Fizz”
  • 7 应该打印 “7”
  • 15 应该打印 “FizzBuzz”
  • 100 应该打印 “Buzz”

开始之前: 这个问题看起来非常简单,但很多很多开发者都难以解决它。我亲眼见过这种情况,所以不要有压力 —— 仅仅尝试解决这个问题本身就会让你有所收获。

你已经掌握了解决这个问题所需的所有知识,但如果你需要一些提示,下面会给出一些。

请先尝试构建这个练习项目吧。

这里有一些提示:

  1. 你可以使用.isMultiple(of:)来检查一个数是否是另一个数的倍数。例如,i.isMultiple(of: 3)
  2. 在这个问题中,你需要先检查是否是 3 和 5 的倍数,因为这是最特殊的情况,然后再检查是否是 3 的倍数,接着检查是否是 5 的倍数,最后用else块来处理所有其他数字。
  3. 你既可以使用&&来检查同时是 3 和 5 的倍数的数字,也可以使用嵌套的if语句。
  4. 你需要从 1 数到 100,所以使用...而不是..<

本站使用 VitePress 制作