3.2.4 控制流

原文链接: https://kotlinlang.org/docs/kotlin-tour-control-flow.html

3.2.4 控制流

与其他编程语言一样,Kotlin 能够根据一段代码的求值结果是否为真来做出判断。这样的代码称为条件表达式。Kotlin 还能创建并遍历循环。

条件表达式

Kotlin 提供了 if 和 when 来检查条件表达式。

注意: 如果你需要在 if 和 when 之间做选择,我们建议使用 when,因为:* 它让你的代码更易读。* 它让添加新的分支更容易。* 它能减少代码中的错误。

if

要使用 if,请把条件表达式放在圆括号 () 中,并把结果为真时要执行的动作放在花括号 {} 中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fun main() {
    val d: Int
    val check = true

    if (check) {
        d = 1
    } else {
        d = 2
    }

    println(d)
    // 1
}

Kotlin 中没有三元运算符 condition ? then : else。取而代之的是,if 可以用作表达式。如果每个动作只有一行代码,花括号 {} 可以省略:

1
2
3
4
5
6
fun main() {
    val a = 1
    val b = 2

    println(if (a > b) a else b) // Returns a value: 2
}

when

当条件表达式有多个分支时,请使用 when。

要使用 when:

  • 把你要求值的值放在圆括号 () 中。
  • 把各个分支放在花括号 {} 中。
  • 在每个分支中使用 -> 把判断条件与满足条件时要执行的动作分开。

when 既可以当作语句使用,也可以当作表达式使用。语句不返回值,而是执行动作。

下面是把 when 当作语句使用的示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fun main() {
    val obj = "Hello"

    when (obj) {
        // Checks whether obj equals to "1"
        "1" -> println("One")
        // Checks whether obj equals to "Hello"
        "Hello" -> println("Greeting")
        // Default statement
        else -> println("Unknown")
    }
    // Greeting
}

注意: 请注意,所有分支条件都会依次检查,直到其中一个被满足为止。因此只有第一个合适的分支会被执行。

表达式会返回一个值,供你在代码后面使用。

下面是把 when 当作表达式使用的示例。这个 when 表达式立即被赋给一个变量,随后该变量被 println() 函数使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
fun main() {
    val obj = "Hello"

    val result = when (obj) {
        // If obj equals "1", sets result to "one"
        "1" -> "One"
        // If obj equals "Hello", sets result to "Greeting"
        "Hello" -> "Greeting"
        // Sets result to "Unknown" if no previous condition is satisfied
        else -> "Unknown"
    }
    println(result)
    // Greeting
}

到目前为止你看到的 when 示例都有一个主语:obj。但 when 也可以不带主语使用。

这个示例使用不带主语的 when 表达式来检查一串布尔表达式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fun main() {
    val trafficLightState = "Red" // This can be "Green", "Yellow", or "Red"

    val trafficAction = when {
        trafficLightState == "Green" -> "Go"
        trafficLightState == "Yellow" -> "Slow down"
        trafficLightState == "Red" -> "Stop"
        else -> "Malfunction"
    }

    println(trafficAction)
    // Stop
}

不过,你也可以用同样的代码,但把 trafficLightState 作为主语:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fun main() {
    val trafficLightState = "Red" // This can be "Green", "Yellow", or "Red"

    val trafficAction = when (trafficLightState) {
        "Green" -> "Go"
        "Yellow" -> "Slow down"
        "Red" -> "Stop"
        else -> "Malfunction"
    }

    println(trafficAction)
    // Stop
}

带主语使用 when 能让代码更易读、更易维护。当你为 when 表达式指定主语时,它还有助于 Kotlin 检查是否覆盖了所有可能的情况。否则,如果不带主语使用 when 表达式,你就必须提供 else 分支。

条件表达式练习

习题 1

创建一个小游戏:掷两个骰子,如果点数相同就算赢。用 if 在点数相同时打印 You win :),否则打印 You lose :(。

提示: 在这个练习中,你要导入一个包,以便使用 Random.nextInt() 函数获得一个随机的 Int。关于导入包的更多信息,请参阅包与导入。

提示

使用相等运算符(==)来比较两个骰子的结果。

1
2
3
4
5
6
7
import kotlin.random.Random

fun main() {
    val firstResult = Random.nextInt(6)
    val secondResult = Random.nextInt(6)
    // Write your code here
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import kotlin.random.Random

fun main() {
    val firstResult = Random.nextInt(6)
    val secondResult = Random.nextInt(6)
    if (firstResult == secondResult)
        println("You win :)")
    else
        println("You lose :(")
}

示例解答

习题 2

用 when 表达式改写下面的程序,让它在输入游戏手柄按键名称时打印对应的动作。

| 按键 | 动作 | | A | Yes | | B | No | | X | Menu | | Y | Nothing | | Other | There is no such button |

1
2
3
4
5
6
7
fun main() {
    val button = "A"

    println(
        // Write your code here
    )
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
fun main() {
    val button = "A"

    println(
        when (button) {
            "A" -> "Yes"
            "B" -> "No"
            "X" -> "Menu"
            "Y" -> "Nothing"
            else -> "There is no such button"
        }
    )
}

示例解答

区间

在讲循环之前,先了解如何构造供循环遍历的区间会很有用。

在 Kotlin 中创建区间最常见的方式是使用 .. 运算符。例如,1..4 等价于 1, 2, 3, 4。

要声明一个不包含结束值的区间,请使用 ..< 运算符。例如,1..<4 等价于 1, 2, 3。

要声明一个逆序区间,请使用 downTo。例如,4 downTo 1 等价于 4, 3, 2, 1。

要声明一个步长不为 1 的区间,请使用 step 以及你想要的步长值。例如,1..5 step 2 等价于 1, 3, 5。

你也可以对 Char 区间做同样的操作:

  • 'a'..'d' 等价于 'a', 'b', 'c', 'd'
  • 'z' downTo 's' step 2 等价于 'z', 'x', 'v', 't'

循环

编程中最常见的两种循环结构是 for 和 while。用 for 遍历一段取值区间并执行动作。用 while 不断执行某个动作,直到满足特定条件。

for

运用刚学到的区间知识,你可以创建一个 for 循环,遍历 1 到 5 的数字并每次都打印出来。

把迭代变量和区间放在圆括号 () 中,并使用关键字 in。把你想要完成的动作放在花括号 {} 中:

1
2
3
4
5
6
7
fun main() {
    for (number in 1..5) {
        // number is the iterator and 1..5 is the range
        print(number)
    }
    // 12345
}

集合也可以用循环遍历:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fun main() {
    val cakes = listOf("carrot", "cheese", "chocolate")

    for (cake in cakes) {
        println("Yummy, it's a $cake cake!")
    }
    // Yummy, it's a carrot cake!
    // Yummy, it's a cheese cake!
    // Yummy, it's a chocolate cake!
}

while

while 有两种用法:

  • 在条件表达式为真时执行代码块。(while)
  • 先执行一次代码块,然后再检查条件表达式。(do-while)

第一种用法(while):

  • 把你希望 while 循环继续执行的条件表达式声明在圆括号 () 中。
  • 把你想要完成的动作放在花括号 {} 中。

提示: 下面的示例使用自增运算符 ++ 来递增 cakesEaten 变量的值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fun main() {
    var cakesEaten = 0
    while (cakesEaten < 3) {
        println("Eat a cake")
        cakesEaten++
    }
    // Eat a cake
    // Eat a cake
    // Eat a cake
}

第二种用法(do-while):

  • 把你希望 while 循环继续执行的条件表达式声明在圆括号 () 中。
  • 使用关键字 do,把你要完成的动作定义在花括号 {} 中。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
fun main() {
    var cakesEaten = 0
    var cakesBaked = 0
    while (cakesEaten < 3) {
        println("Eat a cake")
        cakesEaten++
    }
    do {
        println("Bake a cake")
        cakesBaked++
    } while (cakesBaked < cakesEaten)
    // Eat a cake
    // Eat a cake
    // Eat a cake
    // Bake a cake
    // Bake a cake
    // Bake a cake
}

关于条件表达式和循环的更多信息与示例,请参阅条件与循环。

现在你已经了解了 Kotlin 控制流的基础知识,接下来该学习如何编写你自己的函数了。

循环练习

习题 1

你有一个程序,它一直在数披萨片数,直到凑满一整张 8 片的披萨。请用两种方式重构这个程序:

  • 使用 while 循环。
  • 使用 do-while 循环。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
fun main() {
    var pizzaSlices = 0
    // Start refactoring here
    pizzaSlices++
    println("There's only $pizzaSlices slice/s of pizza :(")
    pizzaSlices++
    println("There's only $pizzaSlices slice/s of pizza :(")
    pizzaSlices++
    println("There's only $pizzaSlices slice/s of pizza :(")
    pizzaSlices++
    println("There's only $pizzaSlices slice/s of pizza :(")
    pizzaSlices++
    println("There's only $pizzaSlices slice/s of pizza :(")
    pizzaSlices++
    println("There's only $pizzaSlices slice/s of pizza :(")
    pizzaSlices++
    println("There's only $pizzaSlices slice/s of pizza :(")
    pizzaSlices++
    // End refactoring here
    println("There are $pizzaSlices slices of pizza. Hooray! We have a whole pizza! :D")
}
1
2
3
4
5
6
7
8
9
fun main() {
    var pizzaSlices = 0
    while ( pizzaSlices < 7 ) {
        pizzaSlices++
        println("There's only $pizzaSlices slice/s of pizza :(")
    }
    pizzaSlices++
    println("There are $pizzaSlices slices of pizza. Hooray! We have a whole pizza! :D")
}

示例解答 1

1
2
3
4
5
6
7
8
9
fun main() {
    var pizzaSlices = 0
    pizzaSlices++
    do {
        println("There's only $pizzaSlices slice/s of pizza :(")
        pizzaSlices++
    } while ( pizzaSlices < 8 )
    println("There are $pizzaSlices slices of pizza. Hooray! We have a whole pizza! :D")
}

示例解答 2

习题 2

编写一个模拟 Fizz buzz 游戏的程序。你的任务是依次打印 1 到 100 的数字,把能被三整除的数字替换为单词 “fizz”,把能被五整除的数字替换为单词 “buzz”。既能被 3 整除又能被 5 整除的数字必须替换为单词 “fizzbuzz”。

提示 1

用 for 循环来计数,用 when 表达式来决定每一步打印什么。

提示 2

使用取模运算符(%)来得到相除后的余数。使用相等运算符(==)来检查余数是否等于零。

1
2
3
fun main() {
    // Write your code here
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
fun main() {
    for (number in 1..100) {
        println(
            when {
                number % 15 == 0 -> "fizzbuzz"
                number % 3 == 0 -> "fizz"
                number % 5 == 0 -> "buzz"
                else -> "$number"
            }
        )
    }
}

示例解答

习题 3

你有一个单词列表。用 for 和 if 只打印以字母 l 开头的单词。

提示

对 String 类型使用 .startsWith() 函数。

1
2
3
4
fun main() {
    val words = listOf("dinosaur", "limousine", "magazine", "language")
    // Write your code here
}
1
2
3
4
5
6
7
fun main() {
    val words = listOf("dinosaur", "limousine", "magazine", "language")
    for (w in words) {
        if (w.startsWith("l"))
            println(w)
    }
}

示例解答

另请参阅

上一步

下一步