第6天 循环
循环是让计算机如此出色的原因之一:它能够每秒重复执行某些简单任务数十亿次。
当然,循环中具体执行什么任务取决于你:你可能在累加一些数字,可能在读取一些传感器数据,或者可能在每秒重绘屏幕 120 次。正如克雷格・布鲁斯所说:“硬件让机器变快,但软件却可能让快的机器变慢。”
今天你需要完成三个教程,此外还有一个总结和一个 检查练习。 完成每个视频后,你可以阅读可选的额外部分,还有一个简短的测试来帮助你确认是否理解了所教授的内容。
6.1 如何使用 for 循环重复执行任务
作者:Paul Hudson 2021 年 10 月 25 日 已针对 Xcode 16.4 更新
计算机非常擅长执行重复性工作,而 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 这个名称并没有什么特别之处 —— 我们也可以这样写:
for name in platforms {
print("Swift 在 \(name) 上表现很棒。")
}甚至可以这样写:
for rubberChicken in platforms {
print("Swift 在 \(rubberChicken) 上表现很棒。")
}代码的运行效果还是完全一样的。
实际上,Xcode 在这方面很智能:如果你写 for plat,它会识别出有一个名为 platforms 的数组,并会提示自动补全为 for platform in platforms—— 它能识别出 platforms 是复数形式,并为循环变量建议单数形式的名称。当你看到 Xcode 出现这个建议时,按回车键选择它即可。
除了遍历数组(或集合、字典 —— 语法是一样的!),你也可以遍历一个固定的数字范围。例如,我们可以像这样打印出 5 乘以 1 到 12 的乘法表:
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,之后循环就结束了。
你也可以把循环放在另一个循环里面,这称为嵌套循环,就像这样:
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 有一种类似但又不同的范围类型,它数到但不包括最后一个数字:..<。在代码中看会更清楚:
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 循环的讨论之前,还有一件事我想提一下:有时候你想用一个范围来运行一段代码特定的次数,但实际上你并不需要循环变量 —— 你不需要 i 或 j,因为你用不到它们。
在这种情况下,你可以用下划线替换循环变量,像这样:
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 更新
如果你想遍历数组中的元素,你可能会写出这样的代码:
let names = ["Sterling", "Cyril", "Lana", "Ray", "Pam"]
for name in names {
print("\(name) 是一名特工")
}每次循环运行时,Swift 会从 names 数组中取出一个元素,把它放入 name 常量中,然后执行我们的循环体 —— 也就是 print() 方法。
然而,有时候你实际上并不需要当前正在读取的值,这时候就用到下划线了:Swift 会识别出你并不需要这个变量,就不会为你创建这个临时常量了。
当然,Swift 本身也能察觉到这一点 —— 它能看到你是否在循环体中使用了 name,所以即使没有下划线,它也能完成同样的工作。不过,使用下划线对我们理解代码也有类似的帮助:无论循环体中有多少行代码,我们一看代码就能立刻知道循环变量没有被使用。
所以,如果你在循环体中没有使用循环变量,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 让我们可以只指定范围的一部分来轻松创建它们。
例如,如果我们有一个像这样的名字数组:
let names = ["Piper", "Alex", "Suzanne", "Gloria"]我们可以像这样读取一个单独的名字:
print(names[0])有了范围,我们也可以像这样打印一个范围的值:
print(names[1...3])不过,这有一个小风险:如果我们的数组至少没有 4 个元素,那么 1...3 就会出错。幸运的是,我们可以使用单侧范围来表示 “给我从 1 到数组末尾的元素”,像这样:
print(names[1...])所以,范围不仅非常适合遍历特定的值,而且对于从数组中读取一组元素也很有帮助。
【练习题】for 循环
问题 1/12:这段代码会打印三行文本 —— 对还是错?
for _ in 0...3 {
print("Hip hip hurray!")
}问题 2/12:这段代码会打印三行文本 —— 对还是错?
let count = 1...3
for _ in count {
print("There's no place like home.")
}问题 3/12:这段代码会打印三行文本 —— 对还是错?
for i in 4...6 {
print("Star Wars: Episode \(i)")
}问题 4/12:这段代码会打印三行文本 —— 对还是错?
for beatle in "John", "Paul", "Ringo" {
print("\(beatle) was in the Beatles")
}问题 5/12:这段代码会打印三行文本 —— 对还是错?
let albums = ["1989", "Red"]
for album in albums {
print("\(album) was a great album!")
}问题 6/12:这段代码会打印三行文本 —— 对还是错?
var names = ["John", "Sophie", "Lottie"]
for name in names {
print("Hello, \(name)!")
}问题 7/12:这段代码会打印三行文本 —— 对还是错?
var numbers = [1, 2, 3, 4, 5, 6]
for number in numbers {
if number.isMultiple(of: 2) {
print(number)
}
}问题 8/12:这段代码会打印三行文本 —— 对还是错?
print("Haters gonna ")
for _ in 1...4 {
print("hate")
}问题 9/12:这段代码会打印三行文本 —— 对还是错?
for number in [2, 3, 5] {
print("\(number) is a prime number.")
}问题 10/12:这段代码会打印三行文本 —— 对还是错?
let score = 100
for count in 10..<13 {
print("I'm counting to \(count)")
}问题 11/12:这段代码会打印三行文本 —— 对还是错?
for i in 1...8 {
if i < 3 {
print("\(i) is a small number")
}
}问题 12/12:这段代码会打印三行文本 —— 对还是错?
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 循环示例,让我们开始了解:
var countdown = 10
while countdown > 0 {
print("\(countdown)…")
countdown -= 1
}
print("发射!")这段代码创建了一个从 10 开始的整数计数器,然后启动了一个条件为 countdown > 0 的 while 循环。所以,循环体(打印数字并减 1)会持续运行,直到 countdown 等于或小于 0,这时循环会结束,然后打印最后的消息。
当你不知道循环要执行多少次时,while 循环非常有用。为了说明这一点,我想向你介绍 Int 和 Double 都具有的一个非常实用的功能:random(in:)。给它一个数字范围,它会返回该范围内的一个随机 Int 或 Double。
例如,下面的代码会创建一个 1 到 1000 之间的新整数:
let id = Int.random(in: 1...1000)而这段代码会创建一个 0 到 1 之间的随机小数:
let amount = Double.random(in: 0...1)我们可以将这个功能与 while 循环结合起来,一次又一次地掷虚拟的 20 面骰子,直到掷出 20 点才结束循环 —— 对于所有《龙与地下城》玩家来说,这可是一次暴击哦。
实现这个功能的代码如下:
// 创建一个整数来存储我们的掷骰结果
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:这个循环会打印五行文本 —— 对还是错?
while 0 < 5 {
print("我在数到 5!")
}问题 2/12:这个循环会打印五行文本 —— 对还是错?
let colors = ["红色", "绿色", "蓝色", "橙色", "黄色"]
var colorCounter = 0
while colorCounter < 5 {
print("\(colors[colorCounter]) 是一种受欢迎的颜色。")
colorCounter += 1
}问题 3/12:这个循环会打印五行文本 —— 对还是错?
var counter = 2
while counter < 64 {
print("\(counter) 是 2 的幂。")
counter *= 2
}问题 4/12:这个循环会打印五行文本 —— 对还是错?
var page: Int = 0
while page <= 5 {
page += 1
print("我正在读第 \(page) 页。")
}问题 5/12:这个循环会打印五行文本 —— 对还是错?
var pianoLesson = 1
while pianoLesson < 5 {
print("这是第 \(pianoLesson) 节课")
pianoLesson += 1
}问题 6/12:这个循环会打印五行文本 —— 对还是错?
var cats: Int = 0
while cats < 10 {
cats += 1
print("我又养了一只猫。")
if cats == 4 {
print("猫够多了!")
cats = 10
}
}问题 7/12:这个循环会打印五行文本 —— 对还是错?
var itemsSold: Int = 0
while itemsSold < 5000 {
itemsSold += 100
if itemsSold.isMultiple(of: 10000) {
print("售出 \(itemsSold) 件商品——一个重要的里程碑!")
}
}问题 8/12:这个循环会打印五行文本 —— 对还是错?
var number: Int = 10
while number > 0 {
number -= 2
if number.isMultiple(of: 2) {
print("\(number) 是一个偶数。")
}
}问题 9/12:这个循环会打印五行文本 —— 对还是错?
let bottles = 10
while bottles > 0 {
bottles -= 2
print("\(bottles) 个绿色瓶子。")
}问题 10/12:这个循环会打印五行文本 —— 对还是错?
var position = 5
while position > 0 {
print("\(position)!")
position -= 1
}问题 11/12:这个循环会打印五行文本 —— 对还是错?
var averageScore = 2.5
while averageScore < 15.0 {
averageScore += 2.5
print("平均分数是 \(averageScore)")
}问题 12/12:这个循环会打印五行文本 —— 对还是错?
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 会立即停止执行当前循环迭代,跳转到循环中的下一个项,然后像正常情况一样继续。这通常用在循环的开头,用于排除那些没有通过你设定的测试的循环变量。
下面是一个例子:
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 个公倍数:
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 数到 100,000,将每个循环变量赋给
i。 - 如果
i是第一个和第二个数字的公倍数,则将其添加到整数数组中。 - 一旦我们得到 10 个公倍数,就调用
break退出循环。 - 打印结果数组。
所以,当你想跳过当前循环迭代的其余部分时使用 continue,当你想跳过所有剩余的循环迭代时使用 break。
【可选阅读】为什么要退出循环?
作者:Paul Hudson 2020 年 6 月 5 日 已为 Xcode 16.4 更新
Swift 的 break 关键字让我们可以立即退出循环,无论我们谈论的是哪种循环。很多时候你不需要这个,因为你正在遍历数组中的项并想处理所有项,或者因为你要从 1 数到 10 并想处理所有这些值。
然而,有时你确实想提前结束循环。例如,如果你有一个分数数组,并且想知道玩家在得到 0 分之前获得了多少个分数,你可能会这样写:
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 的带标签语句允许我们为代码的某些部分命名,它最常用于跳出嵌套循环。
为了演示它们,让我们看一个例子,我们试图找出解锁保险箱的正确动作组合。我们可以先定义一个包含所有可能动作的数组:
let options = ["上", "下", "左", "右"]为了测试,下面是我们要猜测的秘密组合:
let secretCombination = ["上", "上", "右"]为了找到这个组合,我们需要生成包含所有可能的三个动作的数组:
- 上、上、上
- 上、上、下
- 上、上、左
- 上、上、右
- 上、下、左
- 上、下、右
…… 你懂的。
为了实现这一点,我们可以编写三个循环,一个嵌套在另一个里面,就像这样:
for option1 in options {
for option2 in options {
for option3 in options {
print("在循环中")
let attempt = [option1, option2, option3]
if attempt == secretCombination {
print("组合是 \(attempt)!")
}
}
}
}这段代码多次遍历相同的项来创建一个 attempt 数组,如果它的尝试与秘密组合匹配,就会打印一条消息。
但这段代码有一个问题:一旦我们找到组合,循环就应该结束了,为什么它们还在继续运行呢?我们真正想说的是 “一旦找到组合,立即退出所有循环”—— 这就是带标签语句的用武之地。它们让我们可以这样写:
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:这个循环会打印一些文本 —— 对还是错?
var isActive = false
while isActive {
print("正在检查用户输入...")
}问题 2/12:这个循环会打印一些文本 —— 对还是错?
var counter = 0
while counter < 5 {
counter += 1
print("计数:\(counter)")
}问题 3/12:这个循环会打印一些文本 —— 对还是错?
for name in ["John", "Paul", "George"] {
break
print("欢迎,\(name)!")
}问题 4/12:这个循环会打印一些文本 —— 对还是错?
var password = "1"
while true {
password += "1"
if password == "11111" {
print("这是一个很糟糕的密码。")
}
break
}问题 5/12:这个循环会打印一些文本 —— 对还是错?
repeat while true {
print("正在获取更新")
}问题 6/12:这个循环会打印一些文本 —— 对还是错?
for i in 1...10 {
if i == 8 {
print("找到数字 8 了!")
}
}问题 7/12:这个循环会打印一些文本 —— 对还是错?
var people = 2
while people < 10 {
people += 2
if people == 10 {
print("我们有 10 个人了。")
}
}问题 8/12:这个循环会打印一些文本 —— 对还是错?
for i in 1..<10 {
if i == 10 {
print("找到数字 10 了!")
}
}问题 9/12:这个循环会打印一些文本 —— 对还是错?
while true {
print("你好,世界!")
}问题 10/12:这个循环会打印一些文本 —— 对还是错?
for person in ["Taylor", "Justin", "Adele"] {
print("你好,\(person)!")
}问题 11/12:这个循环会打印一些文本 —— 对还是错?
for i in 1...15 {
if i.isMultiple(of: 3) {
if i.isMultiple(of: 5) {
print("\(i) 是 3 和 5 的公倍数。")
}
}
}问题 12/12:这个循环会打印一些文本 —— 对还是错?
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,对于每个数字:
- 如果它是 3 的倍数,打印 “Fizz”
- 如果它是 5 的倍数,打印 “Buzz”
- 如果它既是 3 的倍数又是 5 的倍数,打印 “FizzBuzz”
- 否则,只需打印该数字。
所以,当你的代码运行时,应该会得到以下一些示例结果:
- 1 应该打印 “1”
- 2 应该打印 “2”
- 3 应该打印 “Fizz”
- 4 应该打印 “4”
- 5 应该打印 “Buzz”
- 6 应该打印 “Fizz”
- 7 应该打印 “7”
- …
- 15 应该打印 “FizzBuzz”
- …
- 100 应该打印 “Buzz”
开始之前: 这个问题看起来非常简单,但很多很多开发者都难以解决它。我亲眼见过这种情况,所以不要有压力 —— 仅仅尝试解决这个问题本身就会让你有所收获。
你已经掌握了解决这个问题所需的所有知识,但如果你需要一些提示,下面会给出一些。
请先尝试构建这个练习项目吧。
这里有一些提示:
- 你可以使用
.isMultiple(of:)来检查一个数是否是另一个数的倍数。例如,i.isMultiple(of: 3)。 - 在这个问题中,你需要先检查是否是 3 和 5 的倍数,因为这是最特殊的情况,然后再检查是否是 3 的倍数,接着检查是否是 5 的倍数,最后用
else块来处理所有其他数字。 - 你既可以使用
&&来检查同时是 3 和 5 的倍数的数字,也可以使用嵌套的if语句。 - 你需要从 1 数到 100,所以使用
...而不是..<。