练习题:Kotlin 基础

1. 开始之前

您已经为学习 Kotlin 编程基础付出了努力,现在是时候将所学知识付诸实践了。

这些练习测试您对所学概念的理解。它们以现实世界中的用例为主题,其中一些您可能以前遇到过。

按照说明找到每个问题的解决方案。如果您遇到困难,一些练习有提示可以帮助您。解决方案代码在最后提供,但强烈建议您在查看答案之前先解决练习。

将解决方案视为解决问题的其中一种方法,并随时以您觉得舒适的方式进行试验。您可以通过多种方式解决一些练习,并为函数和变量使用不同的名称。

以您舒适的速度完成这些问题。虽然列出了持续时间,但没有必要遵守这些时间,因为它们只是估计。鼓励您花尽可能多的时间认真解决每个问题。

建议您使用 Kotlin Playground 来解决这些练习。

先决条件

您需要什么

  • 一台连接互联网的电脑和一个网页浏览器

2. 打印消息

告诉您的朋友您在这个路径中学习了什么。

  • 您能编写一个在四行上打印以下消息的 main() 函数吗?
Use the val keyword when the value doesn't change. 
Use the var keyword when the value can change.
When you define a function, you define the parameters that can be passed to it. 
When you call a function, you pass arguments for the parameters.

3. 修复编译错误

此程序打印一条消息,通知用户他们收到了朋友的聊天消息。

fun main() { 
    println("New chat message from a friend'}
}
  1. 你能找出此程序中编译错误的根本原因并修复它们吗?
  2. 代码是否使用适当的符号来指示字符串和函数参数的开始和结束?

提示:您可以使用 Kotlin Playground 运行代码并查看编译错误。

修复错误后,程序应该可以编译通过,并且打印以下输出

New chat message from a friend

4. 字符串模板

此程序通知用户即将针对特定商品进行促销销售。它包含一个字符串模板,该模板依赖于 discountPercentage 变量来表示折扣百分比,以及 item 变量来表示促销商品。

fun main() {
    val discountPercentage: Int = 0
    val offer: String = ""
    val item = "Google Chromecast"
    discountPercentage = 20
    offer = "Sale - Up to $discountPercentage% discount on $item! Hurry up!"
    
    println(offer)
}
  1. 你能找出错误的根本原因并修复它们吗?
  2. 在您在 Kotlin Playground 中运行代码之前,您可以确定此程序的输出吗?

提示:您可以重新分配只读变量的值吗?

修复错误后,程序应该可以编译通过,并且打印以下输出

Sale - Up to 20% discount on Google Chromecast! Hurry up!

5. 字符串串联

此程序显示聚会总人数。聚会上既有成年人又有小孩。 numberOfAdults 变量保存聚会上的成年人数,而 numberOfKids 变量保存小孩人数。

fun main() {
    val numberOfAdults = "20"
    val numberOfKids = "30"
    val total = numberOfAdults + numberOfKids
    println("The total party size is: $total")
}

步骤 1

  • 在您在 Kotlin Playground 中运行代码之前,您可以确定此程序的输出吗?

在您确定输出后,在 Kotlin Playground 中运行代码,然后检查您的输出是否与显示的输出匹配。

提示:当您对两个字符串使用 + 运算符时会发生什么?

步骤 2

代码可以运行并打印一些输出,但是输出没有显示参加聚会的人员总数。

  • 你能找到代码中的问题并修复它,使其打印以下输出吗?
The total party size is: 50

6. 消息格式化

此程序显示员工本月收到的总工资。总工资分为两部分: baseSalary 变量,员工每月收到;以及 bonusAmount 变量,这是奖励给员工的额外奖金。

fun main() {
    val baseSalary = 5000
    val bonusAmount = 1000
    val totalSalary = "$baseSalary + $bonusAmount"
    println("Congratulations for your bonus! You will receive a total of $totalSalary (additional bonus).")
}
  1. 您可以在 Kotlin Playground 中运行它之前确定此代码的输出吗?
  2. 当您在 Kotlin Playground 中运行代码时,它是否打印了您期望的输出?

7. 实现基本的数学运算

在此练习中,您将编写一个执行基本的数学运算并打印输出的程序。

步骤 1

main() 函数包含一个编译错误

fun main() {
    val firstNumber = 10
    val secondNumber = 5
    
    println("$firstNumber + $secondNumber = $result")
}
  • 你能修复错误,使程序打印以下输出吗?
10 + 5 = 15

步骤 2

代码可以运行,但添加两个数字的逻辑位于 result 变量中,这使得您的代码难以重用。相反,您可以将加法运算提取到一个 add() 函数中,使代码可重用。为此,请使用以下代码更新您的代码。请注意,该代码现在引入了一个名为 thirdNumber 的新 val,并使用 firstNumber 打印该新变量的结果。

fun main() {
    val firstNumber = 10
    val secondNumber = 5
    val thirdNumber = 8
    
    val result = add(firstNumber, secondNumber)
    val anotherResult = add(firstNumber, thirdNumber)

    println("$firstNumber + $secondNumber = $result")
    println("$firstNumber + $thirdNumber = $anotherResult")
}

// Define add() function below this line
  • 你能定义 add() 函数,使程序打印以下输出吗?
10 + 5 = 15
10 + 8 = 18

步骤 3

现在,您有一个可重用的函数来添加两个数字。

  • 您能像实现 add() 函数一样实现 subtract() 函数吗?修改 main() 函数,使其也使用 subtract() 函数,以便您可以验证它按预期工作。

提示:考虑加法、减法和其他数学运算之间的区别。从那里开始解决代码。

8. 默认参数

Gmail 有一项功能,可以在新设备上尝试登录时向用户发送通知。

在此练习中,您将编写一个程序,使用以下消息模板向用户显示消息

There's a new sign-in request on operatingSystem for your Google Account emailId.

您需要实现一个函数,该函数接受一个 operatingSystem 参数和一个 emailId 参数,构建指定格式的消息,并返回该消息。

例如,如果函数使用 "Chrome OS" 作为 operatingSystem 和 "[email protected]" 作为 emailId 被调用,它应该返回以下字符串

There's a new sign-in request on Chrome OS for your Google Account [email protected].

步骤 1

  1. 你能在该程序中实现 displayAlertMessage() 函数,使其打印显示的输出吗?
fun main() {
    val operatingSystem = "Chrome OS"
    val emailId = "[email protected]"

    println(displayAlertMessage(operatingSystem, emailId))
}

// Define your displayAlertMessage() below this line.
  1. 您的程序是否打印以下输出?
There's a new sign-in request on Chrome OS for your Google Account [email protected].

步骤 2

做得很好!您显示了消息。但是,在某些情况下,您发现无法确定用户的操作系统。在这种情况下,您需要将操作系统名称指定为 Unknown OS。您可以进一步优化代码,以便不必每次调用函数时都传递 Unknown OS 参数。

  1. 你能找到一种方法,使用此信息来优化代码,使其打印以下输出吗?
There's a new sign-in request on Unknown OS for your Google Account [email protected].

There's a new sign-in request on Windows for your Google Account [email protected]. 

There's a new sign-in request on Mac OS for your Google Account [email protected]. 
  1. 要打印上面的消息,请使用以下代码替换 main() 函数实现
fun main() {
    val firstUserEmailId = "[email protected]"

    // The following line of code assumes that you named your parameter as emailId. 
    // If you named it differently, feel free to update the name.
    println(displayAlertMessage(emailId = firstUserEmailId))
    println()

    val secondUserOperatingSystem = "Windows"
    val secondUserEmailId = "[email protected]"

    println(displayAlertMessage(secondUserOperatingSystem, secondUserEmailId))
    println()

    val thirdUserOperatingSystem = "Mac OS"
    val thirdUserEmailId = "[email protected]"

    println(displayAlertMessage(thirdUserOperatingSystem, thirdUserEmailId))
    println()
}

9. 步数计

步数计是一种电子设备,用于计算所走步数。如今,几乎所有手机、智能手表和健身设备都内置了步数计。健康和健身应用程序使用内置的步数计来计算用户所走步数。此函数根据用户步数计算用户燃烧的卡路里数。

  • 你能根据最佳实践重命名此程序中的函数、函数参数和变量吗?
fun main() {
    val Steps = 4000
    val caloriesBurned = PEDOMETERstepsTOcalories(Steps);
    println("Walking $Steps steps burns $caloriesBurned calories") 
}

fun PEDOMETERstepsTOcalories(NumberOFStepS: Int): Double {
    val CaloriesBURNEDforEachStep = 0.04
    val TotalCALORIESburned = NumberOFStepS * CaloriesBURNEDforEachStep
    return TotalCALORIESburned
}

10. 比较两个数字

现代手机内置了一项功能,用于跟踪屏幕时间,即您每天在手机上花费的时间。

在此练习中,您将实现一个函数,该函数比较您今天在手机上花费的时间(以分钟为单位)与昨天花费的时间。该函数接受两个整数参数,并返回一个布尔值。

第一个参数保存您今天花费的分钟数,第二个参数保存您昨天花费的分钟数。如果今天在手机上花费的时间比昨天多,则该函数返回 true 值。否则,它返回 false 值。

例如,如果您使用以下命名参数调用该函数

  • timeSpentToday = 300timeSpentYesterday = 250,则该函数返回 true 值。
  • timeSpentToday = 300timeSpentYesterday = 300,则该函数返回 false 值。
  • timeSpentToday = 200timeSpentYesterday = 220,则该函数返回 false 值。

提示:如果运算符之前的数值大于运算符之后的数值,则 > 比较运算符返回 true 值。否则,它返回 false 值。

11. 将重复代码移入函数

此程序显示不同城市的实时天气情况。它包括城市名称、当天的最高和最低温度以及降雨概率。

fun main() {
    println("City: Ankara")
    println("Low temperature: 27, High temperature: 31")
    println("Chance of rain: 82%")
    println()

    println("City: Tokyo")
    println("Low temperature: 32, High temperature: 36")
    println("Chance of rain: 10%")
    println()
    
    println("City: Cape Town")
    println("Low temperature: 59, High temperature: 64")
    println("Chance of rain: 2%")
    println()
    
    println("City: Guatemala City")
    println("Low temperature: 50, High temperature: 55")
    println("Chance of rain: 7%")
    println()
}

打印每个城市天气的代码有很多相似之处。例如,一些短语重复出现多次,例如 "City:""Low temperature:"。类似的重复代码会增加程序中出现错误的风险。对于某个城市,您可能会有一个拼写错误,或者您可能会忘记一些天气细节。

  1. 你能创建一个函数来打印单个城市的天气信息,以减少 main() 函数中的重复,然后对其余城市执行相同的操作吗?
  2. 你能更新 main() 函数,使其为每个城市调用你创建的函数,并将适当的天气信息作为参数传递吗?

12. 解决方案代码

该解决方案使用 println() 函数在每行上打印消息。

fun main() {
    println("Use the val keyword when the value doesn't change.")
    println("Use the var keyword when the value can change.")
    println("When you define a function, you define the parameters that can be passed to it.")
    println("When you call a function, you pass arguments for the parameters.")
}

修复编译错误

该代码包含两个编译错误

  1. 字符串应该以双引号而不是单引号结束。
  2. 函数参数应该以括号而不是大括号结束。
fun main() { 
    println("New chat message from a friend")
}

字符串模板

编译错误是由于 discountPercentageoffer 只读变量被分配给新值造成的;不允许这种分配。

fun main() {
    val discountPercentage = 20
    val item = "Google Chromecast"
    val offer = "Sale  - Up to $discountPercentage% discount off $item! Hurry Up!"

    println(offer)
}

作为替代方案,你可以使用 var 关键字声明 discountPercentage 整数和 offer 字符串。但是,它们的值在程序上下文中是不可变的,所以你可以坚持使用 val 关键字。

字符串连接

步骤 1

程序打印以下输出

The total party size is: 2030 

这是一个技巧问题。当 + 运算符用于 String 值时,它会产生一个连接的字符串。整数被包装在双引号中,所以它们被视为字符串而不是整数,因此输出为 2030

步骤 2

可以删除 numberOfAdultsnumberOfKids 变量周围的双引号,将其转换为 Int 变量。

fun main() {
    val numberOfAdults = 20
    val numberOfKids = 30
    val total = numberOfAdults + numberOfKids
    println("The total party size is: $total")
}

如果你记得,Kotlin 编译器可以根据分配给变量的值推断变量的类型。在本例中,编译器推断 numberOfAdultsnumberOfKids 变量为 Int 类型。

消息格式

程序打印以下输出

Congratulations for your bonus! You will receive a total of 5000 + 1000 (additional bonus).

"$baseSalary + $bonusAmount" 使用模板表达式语法。在模板表达式中,代码首先被求值,然后结果被连接到字符串中。

在问题中,$baseSalary 变量被求值为 5000$bonusAmount 变量被求值为 1000。然后,结果被连接起来生成 "5000 + 1000" 并赋值给 result 变量。

实现基本的数学运算

步骤 1

使用 val 关键字定义一个不可变的 result 变量,然后将加法运算的结果赋值给它

fun main() {
    val firstNumber = 10
    val secondNumber = 5
    
    val result = firstNumber + secondNumber
    println("$firstNumber + $secondNumber = $result")
}

步骤 2

  1. 创建一个 add() 函数,该函数接受一个 firstNumber 参数和一个 secondNumber 参数,两者都是 Int 类型,并返回一个 Int 值。
  2. add() 函数体中输入加法运算的代码,然后使用 return 关键字返回运算的结果。
fun add(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber + secondNumber
}

步骤 3

  1. 定义一个 subtract() 函数,该函数接受一个 firstNumber 参数和一个 secondNumber 参数,两者都是 Int 类型,并返回一个 Int 值。
  2. subtract() 函数体中输入减法运算的代码,然后使用 return 关键字返回运算的结果。
fun subtract(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber - secondNumber
}
  1. 修改 main() 函数以使用新的 subtract() 函数。一个示例解决方案可能如下所示
fun main() {
    val firstNumber = 10
    val secondNumber = 5
    val thirdNumber = 8
    
    val result = add(firstNumber, secondNumber)
    val anotherResult = subtract(firstNumber, thirdNumber)

    println("$firstNumber + $secondNumber = $result")
    println("$firstNumber - $thirdNumber = $anotherResult")
}

fun add(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber + secondNumber
}

fun subtract(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber - secondNumber
}

默认参数

步骤 1

  1. 创建一个 displayAlertMessage() 函数,该函数接受一个 operatingSystem 参数和一个 emailId 参数,两者都是 String 类型,并返回一个 String 值。
  2. 在函数体中,使用模板表达式更新消息并返回它。
fun displayAlertMessage(operatingSystem: String, emailId: String): String {
    return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}

步骤 2

  • "Unknown OS" 值分配给 operatingSystem 参数。
fun displayAlertMessage(
    operatingSystem: String = "Unknown OS",
    emailId: String
): String {
    return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}

计步器

函数名和变量名应遵循 *骆驼命名法*。

如果名称包含多个单词,则将第一个单词的首字母小写,将后续单词的首字母大写,并删除单词之间的任何空格。

示例函数名包括

  • calculateTip
  • displayMessage
  • takePhoto

示例变量名包括

  • numberOfEmails
  • cityName
  • bookPublicationDate

要了解有关名称的更多信息,请参阅 命名规则

避免使用 Kotlin 关键字 作为函数名,因为这些词在 Kotlin 语言中已经被分配了特定的含义。

你的解决方案代码应该类似于以下代码片段

fun main() {
    val steps = 4000
    val caloriesBurned = pedometerStepsToCalories(steps)
    println("Walking $steps steps burns $caloriesBurned calories") 
}

fun pedometerStepsToCalories(numberOfSteps: Int): Double {
    val caloriesBurnedForEachStep = 0.04
    val totalCaloriesBurned = numberOfSteps * caloriesBurnedForEachStep
    return totalCaloriesBurned
}

比较两个数字

  • 创建一个 compareTime() 函数,该函数接受一个 timeSpentToday 参数和一个 timeSpentYesterday 参数,两者都是 Int 类型,并返回一个 Boolean 值。

该解决方案依赖于 > 比较运算符。运算符被求值为一个 Boolean 值,因此 compareTime() 函数只是返回 timeSpentToday > timeSpentYesterday 的结果。

例如,如果你将 300 参数传递给 timeSpentToday 参数,并将 250 参数传递给 timeSpentYesterday 参数,则函数体被求值为 300 > 250,它返回一个 true 值,因为 300 大于 250。

fun main() {
    println("Have I spent more time using my phone today: ${compareTime(300, 250)}")
    println("Have I spent more time using my phone today: ${compareTime(300, 300)}")
    println("Have I spent more time using my phone today: ${compareTime(200, 220)}")
}

fun compareTime(timeSpentToday: Int, timeSpentYesterday: Int): Boolean {
    return timeSpentToday > timeSpentYesterday
}
Have I spent more time using my phone today: true
Have I spent more time using my phone today: false
Have I spent more time using my phone today: false

将重复代码移到函数中

  1. main() 函数之后创建一个函数,该函数打印出安卡拉市的天气详细信息。

对于函数名,可以使用 printWeatherForCity() 或类似名称。

  1. main() 函数调用该函数。

程序应打印安卡拉的天气详细信息。

fun main() {
    printWeatherForCity()
}

fun printWeatherForCity() {
    println("City: Ankara")
    println("Low temperature: 27, High temperature: 31")
    println("Chance of rain: 82%")
    println()
}

现在你可以创建另一个更灵活的函数,以便它可以打印其他城市的天气详细信息。

  1. 用变量替换 println() 语句中特定于安卡拉的部分。

请记住,对变量名使用骆驼命名法,并在变量之前使用 $ 符号,以便使用变量的值而不是变量名。这些是你在之前的代码实验室中学习过的字符串模板。

fun printWeatherForCity() {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. 更改函数定义,以便这些变量是调用函数时必须传递的参数,并为每个参数指定数据类型。

cityName 参数为 String 类型,而 lowTemphighTempchanceOfRain 参数为 Int 类型。

函数定义中不需要 return 值,因为消息被打印到输出中。

fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. 更新 main() 函数以调用 printWeatherForCity() 函数并将安卡拉的天气详细信息传递进来。

城市名称为 "Ankara",最低气温为 27,最高气温为 31,降雨概率为 82

fun main() {
    printWeatherForCity("Ankara", 27, 31, 82)
}

fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. 运行程序以验证输出是否显示安卡拉的天气详细信息。
  2. 使用其他城市的天气详细信息调用 printWeatherForCity() 函数。
fun main() {
    printWeatherForCity("Ankara", 27, 31, 82)
    printWeatherForCity("Tokyo", 32, 36, 10)
    printWeatherForCity("Cape Town", 59, 64, 2)
    printWeatherForCity("Guatemala City", 50, 55, 7)
}

fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. 运行程序。

它应该打印与原始程序相同的输出,但是现在你的代码更简洁,不包含不必要的重复!打印城市天气详细信息的所有代码都集中在一个地方:printWeatherForCity() 函数。如果你想更改天气详细信息的显示方式,你可以在一个适用于所有城市的地方更改它们。

13. 额外练习

要练习 Kotlin 语言,请查看 JetBrains Academy 的 Kotlin 核心轨道。要跳转到特定主题,请转到 知识图 以查看轨道中涵盖的主题列表。