在Swift中切换语句

我正在学习Swift的语法,并想知道为什么下面的代码不能像我期望的那样工作:

for i in 1...100{ switch (i){ case 1: Int(i%3) == 0 println("Fizz") case 2: Int(i%5) == 0 println("Buzz") default: println("\(i)") } } 

我想打印Fizz每次数字被3(3,6,9,12等)整除,每打印5次就可以打印Buzz。缺less什么拼图?

注意:我用下面的方法解决了这个问题:

 for ( var i = 0; i < 101; i++){ if (Int(i%3) == 0){ println("Fizz") } else if (Int(i%5) == 0){ println("Buzz") } else { println("\(i)") } } 

我想知道如何解决这个使用开关。 谢谢。

FizzBu​​zz游戏的通常规则是用“Fizz”代替3的每一个倍数,“Buzz”代替5的每一个倍数, 以及由“FizzBu​​zz”代替3 5的每个倍数。

这可以通过元组(i % 3, i % 5)上的switch语句完成。 请注意, _表示“任何值”:

 for i in 1 ... 100 { switch (i % 3, i % 5) { case (0, 0): print("FizzBuzz") case (0, _): print("Fizz") case (_, 0): print("Buzz") default: print(i) } } 

在Swift支持值绑定中切换语句。
这允许您将一个匹配特定条件的值(通过where子句求值)赋值给一个临时variables(这里是xy ):

 for i in 1...100 { switch (i){ case let x where x%3 == 0: println("Fizz") case let y where y%5 == 0: println("Buzz") default: println("\(i)") } } 

您也可以在案例主体中使用分配的临时值。

更新:
Matt Gibson在评论中指出,如果你不打算在案例体中使用它,你可以省略赋值给一个临时variables。
所以上面的代码更简洁的版本是:

 for i in 1...100 { switch (i){ case _ where i%3 == 0: println("Fizz") case _ where i%5 == 0: println("Buzz") default: println("\(i)") } } 

注意:你的2个代码样本略有不同(第一个使用0-100作为input,而第二个使用1-100)。 我的示例是基于您的第一个代码片段。

对于来这里的人来说,这只是一个更普遍的答案,只是想知道如何在Swift中使用switch语句。

一般用法

 switch someValue { case valueOne: // executable code case valueTwo: // executable code default: // executable code } 

 let someValue = "horse" switch someValue { case "horse": print("eats grass") case "wolf": print("eats meat") default: print("no match") } 

笔记:

  • 没有break声明是必要的。 这是默认行为。 快速switch情况下不会“跌倒”。 如果您希望在下一个案例中使用代码,则必须明确使用fallthrough关键字。
  • 每个案例都必须包含可执行代码 如果你想忽略一个案例,你可以添加一个break语句。
  • 案件必须详尽无遗。 也就是说,他们必须涵盖每一个可能的价值。 如果包含足够的case语句是不可行的,则可以最后包含一个default语句来捕获任何其他值。

Swift switch语句非常灵活。 以下部分包括使用它的一些其他方法。

匹配多个值

如果您使用逗号分隔值,则可以在单个案例中匹配多个值。 这被称为复合情况

 let someValue = "e" switch someValue { case "a", "b", "c": // executable code case "d", "e": // executable code default: // executable code } 

你也可以匹配整个间隔

 let someValue = 4 switch someValue { case 0..<10: // executable code case 10...100: // executable code default: // executable code } 

你甚至可以使用元组 。 这个例子是从文档改编的。

 let aPoint = (1, 1) switch aPoint { case (0, 0): // only catches an exact match for first and second case (_, 0): // any first, exact second case (-2...2, -2...2): // range for first and second default: // catches anything else } 

价值绑定

有时您可能想要从switch值中创build一个临时常量或variables。 您可以在case陈述后立即执行此操作。 任何使用值绑定的地方,都会匹配任何值。 这与在上面的元组示例中使用_相似。 以下两个示例从文档中修改。

 let anotherPoint = (2, 0) switch anotherPoint { case (let x, 0): // can use x here case (0, let y): // can use y here case let (x, y): // can use x or y here, matches anything so no "default" case is necessary } 

您可以使用where关键字进一步细化匹配。

 let yetAnotherPoint = (1, -1) switch yetAnotherPoint { case let (x, y) where x == y: // executable code case let (x, y) where x == -y: // executable code case let (x, y): // executable code } 

进一步研究

  • 这个答案只是一个快速参考。 请阅读完整的文档以获取更多信息。 这不难理解。

交换机的行业标准行为可能会导致类似“Go to Fail”的错误 。

基本上,代码并不总是看起来像代码在读取时看起来那样,这会导致代码审计人员跳过关键的错误。

为了解决这个问题,苹果已经决定在Swift中切换语句不应该像行业标准一样工作。 尤其是:

  • 每种情况下都会有一个自动中断。 多个案例陈述不可能执行。
  • 如果在理论上可能丢失一个案例陈述,那么这个代码根本就不会编译。 无论提供什么样的价值,迅速的案例陈述中的一个将始终执行。 如果您提供枚举,则必须处理每个枚举值。 如果将新值添加到现有的枚举中,则代码将不会编译,直到添加新的case语句。 如果你提供一个32位的整数,你必须处理32位整数的每一个可能的值。

这是如何做到的

 var i = 0 switch i { case i where i % 5 == 0 && i % 3 == 0: print(" Fizz Buzz") case i where i % 3 == 0 : print("Fizz") case i where i % 5 == 0 : print("Buzz") default: print(i) } 

使用这个代码。 你的逻辑错了。 您的Switch语句不会find接受1和2的情况

 class TEST1{ func print() -> Void{ var i = 0 for i in 1...100{ if Int(i%3) == 0 { println("Fizz") } else if Int(i%5) == 0{ println("Buzz") } else { println("\(i)") } } } } var x = TEST1() x.print()