zoukankan      html  css  js  c++  java
  • Scala流程控制语句

    [toc]

    ## Scala流程控制语句

    > 1. 在程序中,程序运行的流程控制决定程序是如何执行的,是我们必须掌握的,主要有三大流程控制语句。
    > 2. ==Scala语言中控制结构和Java语言中的控制结构基本相同==,在不考虑特殊应用场景的情况下,代码书写方式以及理解方式都没有太大的区别。
    > 1. 顺序控制
    > 2. 分支控制
    > 3. 循环控制

    ### 1. 顺序控制

    > 程序从上到下逐行地执行,中间没有任何判断和跳转。
    >
    > ~~~scala
    > //Scala中定义变量时采用合法的前向引用。如:
    > def main(args : Array[String]) : Unit = {
    > var num1 = 12
    > var num2 = num1 + 2
    > }
    > //错误形式:
    > def main(args : Array[String]) : Unit = {
    > var num2 = num1 + 2
    > var num1 = 12
    > }
    > ~~~
    >
    > ![image-20210323200717370](assets/image-20210323200717370.png)

    ### 2. 分支控制

    > 让程序有选择的的执行,分支控制有三种(与Java相同):
    >
    > 1. 单分支
    > 2. 双分支
    > 3. 多分支

    #### 单分支和双分支

    ~~~scala
    import scala.io.StdIn
    /**
    * @Date 2021/3/23 16:33
    * @Version 10.21
    * @Author DuanChaojie
    */
    object IfDemo01 {
    /**
    * 小技巧:如何乍看某个包下包含的内容?
    * 1、比如我们想看 scala.io 包有什么内容的话
    * 2、强光标放在io上即可,输入ctrl + b
    * 3、强光标放在StdIn上即可,输入ctrl + b看的是StdIn源码
    * @param args
    */
    def main(args: Array[String]): Unit = {

    println("请输入年龄:")
    val age = StdIn.readInt()
    if (age > 18) {
    println("您已经成年!")
    } else {
    println("小屁孩一个")
    }
    }
    }
    ~~~

    > 单分支和双分支课后题

    ~~~scala
    /**
    * @Date 2021/3/23 16:40
    * @Version 10.21
    * @Author DuanChaojie
    */
    object IfElseExercise01 {
    def main(args: Array[String]): Unit = {
    test1(11, 111)
    test2(111.0, 11.0)
    test3(12, 3)
    test4(2000)
    }


    /**
    * 编写程序,声明2个Int型变量并赋值。判断两数之和,如果大于等于50,打印“hello world!”
    *
    * @param n1
    * @param n2
    */
    def test1(n1: Int, n2: Int): Unit = {
    if (n1 + n2 >= 50) {
    println("hello world!")
    }
    }

    /**
    * 编写程序,声明2个Int型变量并赋值。判断两数之和,如果大于等于50,打印“hello world!”
    *
    * @param d1
    * @param d2
    */
    def test2(d1: Double, d2: Double): Unit = {
    if (d1 > 10.0 && d2 < 20.0) {
    println(d1 + d2)
    }
    }

    /**
    * 定义两个变量Int,判断二者的和,是否既能被3又能被5整除,打印提示信息
    *
    * @param n1
    * @param n2
    */
    def test3(n1: Int, n2: Int): Unit = {
    var sum = n1 + n2
    if (sum % 3 == 0 && sum % 5 == 0) {
    println(s"$n1+$n2 既能被3整除又能被5整除")
    }
    }

    /**
    * 判断一个年份是否是闰年,闰年的条件是符合下面二者之一:
    * (1)年份能被4整除,但不能被100整除;(2)能被400整除
    *
    * @param year
    */
    def test4(year: Int): Unit = {
    if (year < 0) {
    println("请输入合理的年份!")
    } else {
    if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
    println(s"$year 年是闰年")
    }
    }
    }
    }
    ~~~

    #### 多分支

    ~~~~scala
    import scala.io.StdIn

    /**
    * @Date 2021/3/23 16:54
    * @Version 10.21
    * @Author DuanChaojie
    */
    object IfDemo02 {
    def main(args: Array[String]): Unit = {
    /**
    * 岳小鹏参加scala考试,他和父亲岳不群达成承诺:
    * 如果:
    * 成绩为100分时,奖励一辆BMW;
    * 成绩为(80,99]时,奖励一台iphone7plus;
    * 当成绩为[60,80]时,奖励一个 iPad;
    * 其它时,什么奖励也没有。
    * 成绩是从控制台输入
    **/
    println("请输入成绩")
    val score = StdIn.readDouble()
    if (score == 100) {
    println("成绩为100分时,奖励一辆BMW")
    //写法1使用范围,写法2就是严格的判断
    } else if (score > 80 && score <= 99) {
    println("成绩为(80,99]时,奖励一台iphone7plus")
    } else if (score >= 60 && score <= 80) {
    println("奖励一个 iPad")
    } else {
    println("没有任何奖励")
    }
    }
    }
    ~~~~

    > 多分支课后题:
    >
    > ~~~~scala
    > /*
    > 求ax2+bx+c=0方程的根。a,b,c分别为函数的参数,
    > 如果:
    > b2-4ac>0,则有两个解;
    > b2-4ac=0,则有一个解;
    > b2-4ac<0,则无解;
    > [a=3 b=100 c=6]
    > 提示1:
    > x1=(-b+sqrt(b2-4ac))/2a
    > X2=(-b-sqrt(b2-4ac))/2a
    > 提示2:
    > sqrt(num) 在 scala 包中(默认引入的) 的math 的包对象有很多方法直接可用.
    > */
    > ~~~~

    ~~~~scala
    /**
    * @Date 2021/3/23 17:02
    * @Version 10.21
    * @Author DuanChaojie
    */
    object IfElseExercise02 {
    def main(args: Array[String]): Unit = {

    /**
    思路的分析
    1. 定义三个变量a,b,c
    2. 使用多分支完成
    3. 因为 b2-4ac会多次使用,因此我们可以先计算,并保持到变量中
    4. 判断,写逻辑
    */

    val a = 3
    val b = 100
    val c = 6
    val m = b * b - 4 * a * c
    var x1 = 0.0
    var x2 = 0.0

    if (m > 0) {
    x1 = (-b + Math.sqrt(m)) / 2 * a
    x2 = (-b - Math.sqrt(m)) / 2 * a
    println("有两个解: \nx1=" + x1.formatted("%.2f") + "\nx2=" + x2.formatted("%.2f"))
    } else if (m == 0) {
    x1 = (-b + Math.sqrt(m)) / 2 * a
    println("有一个解 x1=" + x1)
    } else {
    println("无解..")
    }
    }
    }
    ~~~~

    #### 分支控制if-else 注意事项

    > 1. `如果大括号{}内的逻辑代码只有一行,大括号可以省略, 这点和java 的规定一样。`
    > 2. Scala中任意表达式都是有返回值的,也就意味着if else表达式其实是有返回结果的,具体返回结果的值取决于满足条件的代码体的最后一行内容。
    > 3. Scala中是没有三元运算符,因为 Scala 的if-else 是有返回值的,因此,本身这个语言也不需要三元运算符了,并且可以写在同一行,类似 三元运算

    ~~~scala
    /**
    * @Date 2021/3/23 17:11
    * @Version 10.21
    * @Author DuanChaojie
    */
    object IfElseExercise03 {
    def main(args: Array[String]): Unit = {
    var sumVal = 9
    val result = if (sumVal > 20) {
    "结果大于20"
    }
    //返回的是() 即 Unit
    println("res=" + result)
    }
    }
    ~~~

    #### 嵌套分支

    > 在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层分支外面的分支结构称为外层分支。==嵌套分支不要超过3层==
    >
    > 案例一:

    ~~~scala
    /**
    * @Date 2021/3/23 17:13
    * @Version 10.21
    * @Author DuanChaojie
    */
    object IfElseExercise04 {
    def main(args: Array[String]): Unit = {
    /**
    * 参加百米运动会,如果用时8秒以内进入决赛,否则提示淘汰。
    * 并且根据性别提示进入男子组或女子组。
    * 【可以让学员先练习下5min】, 输入成绩和性别,进行判断。
    */
    println("请输入运动员的成绩:")
    val speed = StdIn.readDouble()
    if (speed <= 8) {
    println("请输入性别")
    val gender = StdIn.readChar()
    if (gender == '男') {
    println("进入男子组")
    } else {
    println("进入女子组")
    }
    } else {
    println("你被淘汰...")
    }
    }
    }
    ~~~

    > 案例二:

    ~~~scala
    /**
    * @Date 2021/3/23 17:16
    * @Version 10.21
    * @Author DuanChaojie
    */
    object IfElseExercise05 {
    def main(args: Array[String]): Unit = {

    /**
    应用案例2
    出票系统:根据淡旺季的月份和年龄, 打印票价 [考虑学生先做5min]
    4_10 旺季:
    成人(18-60):60
    儿童(<18):半价
    老人(>60):1/3
    淡季:
    成人:40
    其他:20
    思路分析
    1. 定义至少三个变量 month , age, ticket
    2. 逻辑上有月份和年龄的判断因此,会使用嵌套分支
    3. 根据对应的业务逻辑完成代码
    */
    println("输入月份")
    val month = StdIn.readInt()
    println("输入年龄")
    val age = StdIn.readInt()
    val tikcet = 60

    if (month >= 4 && month <= 10) {
    if (age >= 18 && age <= 60) {
    println("你的票价是" + tikcet)
    } else if (age < 18) {
    println("你的票价是" + tikcet / 2)
    } else {
    println("你的票价是" + tikcet / 3)
    }
    } else {
    if (age >= 18 && age <= 60) {
    println("你的票价是" + 40)
    } else {
    println("你的票价是" + 20)
    }
    }
    }
    }
    ~~~

    #### switch分支结构TODO

    > 在Scala中没有switch,而是使用`模式匹配`来处理。
    >
    > 模式匹配涉及到的知识点较为综合,因此我们放在==后面讲解。==

    ### 3. 循环控制

    #### ☆for循环控制☆

    > ==Scala 也为for 循环这一常见的控制结构提供了非常多的特性==,这些for 循环的特性被称为for 推导式(for comprehension)或for 表达式(for expression)
    >
    > 范围数据循环方式1

    ~~~~scala
    /**
    * @Date 2021/3/23 17:34
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ForDemo01 {
    def main(args: Array[String]): Unit = {
    //输出10句 "hello,尚硅谷!"
    val start = 1
    val end = 10
    //说明
    //1. start 从哪个数开始循环
    //2. to 是关键字
    //3. end 循环结束的值
    //4. start to end 表示前后闭合
    for (i <- start to end) {

    println("你好,尚硅谷" + i)
    }

    //说明for 这种推导时,也可以直接对集合进行遍历
    var list = List("hello", 10, 30, "tom")
    for (item <- list) {
    println("item=" + item)
    }

    }
    }
    ~~~~

    > 范围数据循环方式2

    ~~~scala
    /**
    * @Date 2021/3/23 17:38
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ForUntilDemo02 {
    def main(args: Array[String]): Unit = {
    //输出10句 "hello,尚硅谷!"
    val start = 1
    val end = 11
    // 循环的范围是 start --- (end - 1)
    for (i <- start until end) {
    println("你好,尚硅谷" + i)
    }
    }
    }
    ~~~

    > `循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为true则进入循环体内部,为false则跳过,类似于continue`

    ~~~scala
    object ForGuard {
    def main(args: Array[String]): Unit = {
    for (i <- 1 to 3 if i != 2) {
    println("i = " + i)
    }
    }
    }
    ~~~

    > 引入变量

    ~~~scala
    object ForVar {
    def main(args: Array[String]): Unit = {
    for (i <- 1 to 3; j = 4 - i) {
    println("j = " + j)
    }
    }
    }
    ~~~

    > 嵌套循环

    ~~~~scala
    object ForMulti {
    def main(args: Array[String]): Unit = {
    for (i <- 1 to 3; j <- 1 to 3) {
    println("i = " + i + "\tj = " + j)
    }

    println("----------------------------")
    // 上面的写法也可以写成:
    for (i <- 1 to 3) {
    for (j <- 1 to 3) {
    println("i = " + i + "\tj = " + j)
    }
    }
    }
    }
    ~~~~

    > 循环返回值:
    >
    > - 将遍历过程中处理的结果返回到一个新Vector集合中,使用yield关键字
    > - `val res = for(i <- 1 to 10) yield i`

    ~~~~scala
    object ForYield {
    def main(args: Array[String]): Unit = {
    /**
    * 说明 val res = for(i <- 1 to 10) yield i 含义
    * 1. 对1 to 10 进行遍历
    * 2. yield i 将每次循环得到i 放入到集合Vector中,并返回给res
    * 3. i 这里是一个代码块,这就意味我们可以对i进行处理
    * 4. 下面的这个方式,就体现出scala一个重要的语法特点,就是将一个集合中个各个数据
    * 进行处理,并返回给新的集合
    */
    val res = for(i <- 1 to 10) yield {
    if(i % 2 == 0){
    i
    }else{
    "不是偶数"
    }
    }
    // Vector(不是偶数, 2, 不是偶数, 4, 不是偶数, 6, 不是偶数, 8, 不是偶数, 10)
    println(res)
    }
    }
    ~~~~

    > `使用花括号{}代替小括号()`
    >
    > ~~~scala
    > //基本案例
    > for(i <- 1 to 3; j = i * 2) {
    > println(" i= " + i + " j= " + j)
    > }
    >
    > //可以写成
    > for{
    > i <- 1 to 3
    > j = i * 2} {
    > println(" i= " + i + " j= " + j)
    > }
    > ~~~
    >
    > 对基本案例说明
    >
    > 1. {}和()对于for表达式来说都可以
    > 2. for 推导式有一个不成文的约定:当for 推导式仅包含单一表达式时使用圆括号,当其包含多个表达式时使用大括号
    > 3. 当使用{} 来换行写表达式时,分号就不用写了
    >
    > 注意事项和细节说明
    >
    > 1. ==Scala 的for循环形式和java是较大差异,这点请同学们注意,但是基本的原理还是一样的。==
    > 2. 思考题:如何使用循环守卫控制步长?

    ~~~scala
    /**
    * @Date 2021/3/23 20:42
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ForStep {
    def main(args: Array[String]): Unit = {

    for (i <- 1 to 10) {
    println("i=" + i)
    }

    //步长控制为2
    println("-------------")

    /**
    * Range(1,10,2)的对应的构建方法是
    * def apply(start: Int, end: Int, step: Int): Range = new Range(start, end, step)
    */
    for (i <- Range(1, 10, 2)) {
    println("i=" + i)
    }

    //控制步长的第二种方式-for循环守卫
    println("**************************")
    for (i <- 1 to 10 if i % 2 == 1) {
    println("i=" + i)
    }
    }
    }
    ~~~

    > For循环练习题

    ~~~scala

    /**
    * @Date 2021/3/23 19:08
    * @Version 10.21
    * @Author DuanChaojie
    */
    object ForExercise01 {
    def main(args: Array[String]): Unit = {
    /**
    for循环练习题:
    打印1~100之间所有是9的倍数的整数的个数及总和.
    完成下面的表达式输出
    */
    val start = 1
    val end = 100
    var count = 0
    var sum = 0

    for (i <- start to end) {
    if (i % 9 == 0) {
    count += 1
    sum += i
    }
    }
    printf("count=%d, sum=%d\n", count, sum)

    //输出加法的循环表达式
    val num = 6
    for (i <- 0 to num) {
    printf("%d + %d = %d\n", i, (num - i), num)
    }

    var list = List(1,2)
    }
    }
    ~~~

    #### while循环控制

    ~~~~scala
    object WhileDemo01 {
    def main(args: Array[String]): Unit = {
    var i = 0
    while(i < 10){
    println("Hello 尚硅谷" + i)
    // 循环变量迭代
    i += 1
    }
    }
    }
    ~~~~

    > 注意事项和细节说明
    >
    > 1. 循环条件是返回一个布尔值的表达式
    > 2. while循环是先判断再执行语句
    > 3. 与If语句不同,While语句本身没有值,即整个While语句的结果是Unit类型的()
    > 4. 因为while中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免的使用变量 ,而变量需要声明在while循环的外部,那么就等同于循环的内部对外部的变量造成了影响,`所以不推荐使用,而是推荐使用for循环。`

    #### do..while循环控制

    ~~~scala
    object DoWhileDemo01 {
    def main(args: Array[String]): Unit = {
    var i = 0
    do {
    println(i + "Hello Scala")
    i += 1
    } while (i < 10)
    }
    }
    ~~~

    > 注意事项和细节说明:
    >
    > 1. 循环条件是返回一个布尔值的表达式
    > 2. do..while循环是先执行,再判断
    > 3. 和while 一样,因为do…while中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免的使用变量 ,而变量需要声明在do...while循环的外部,那么就等同于循环的内部对外部的变量造成了影响`,所以不推荐使用,而是推荐使用for循环`

    #### 多重循环控制

    > 1. 将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do…while均可以作为外层循环和内层循环。`【建议一般使用两层,最多不要超过3层】`
    > 2. 实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
    > 3. 设外层循环次数为m次,内层为n次, 则内层循环体实际上需要执行m*n=mn次。
    >
    > `案例一:`

    ~~~~scala
    object Exercise01 {
    /**
    *应用实例:
    *1.统计三个班成绩情况,每个班有5名同学,求出各个班的平均分和所有班级的平均分[学生的成绩从键盘输入]。
    * 分析思路
    * (1) classNum 表示 班级个数 , stuNum 表示学生个数
    * (2) classScore 表示各个班级总分 totalScore 表示所有班级总分
    * (3) score 表示各个学生成绩
    * (4) 使用循环的方式输入成绩
    *2.统计三个班及格人数,每个班有5名同学。
    *3.打印出九九乘法表
    */

    def main(args: Array[String]): Unit = {
    val classNum = 3
    val stuNum = 5
    var score = 0.0 //分数
    var classScore = 0.0 //班级的总分
    var totalScore = 0.0 //所有班级总分

    for (i <- 1 to classNum) {
    //先将 classScore 清0
    classScore = 0.0
    for (j <- 1 to stuNum) {
    printf("请输入第%d班级的第%d个学生的成绩\n", i, j)
    score = StdIn.readDouble()
    classScore += score
    }
    //累计 totalScore
    totalScore += classScore
    printf("第%d班级的平均分为%.2f\n", i, classScore / stuNum)
    }
    printf("所有班级的平均分为%.2f", totalScore / (stuNum * classNum))
    }
    }
    ~~~~

    > 案例二:

    ```scala
    object Exercise02 {
    def main(args: Array[String]): Unit = {
    /**
    * 2.统计三个班及格人数,每个班有5名同学。
    */
    val classNum = 3
    val stuNum = 5
    var score = 0.0 //分数
    var classScore = 0.0 //班级的总分
    var totalScore = 0.0 //所有班级总分
    var passNum = 0 //统计及格人数
    for (i <- 1 to classNum) {
    //先将 classScore 清0
    classScore = 0.0
    for (j <- 1 to stuNum) {
    printf("请输入第%d班级的第%d个学生的成绩\n", i, j)
    score = StdIn.readDouble()
    if (score >= 60) {
    passNum += 1
    }
    classScore += score
    }
    //累计 totalScore
    totalScore += classScore
    printf("第%d班级的平均分为%.2f\n", i, classScore / stuNum)
    }
    printf("所有班级的平均分为%.2f", totalScore / (stuNum * classNum))
    printf("所有班级的及格人数为%d", passNum)
    }
    }
    ```

    > 案例三:

    ~~~~scala
    /**
    * @Date 2021/3/23 19:44
    * @Version 10.21
    * @Author DuanChaojie
    */
    object Exercice03 {
    def main(args: Array[String]): Unit = {
    //3.打印出九九乘法表
    var num = 9
    for (i <- 1 to num) {
    for (j <- 1 to i) {
    print(s"$j * $i = ${i * j} \t")
    }
    println()
    }
    }
    }
    ~~~~

    #### while循环的中断

    ==Scala内置控制结构特地去掉了break和continue,是为了更好的适应函数化编程,推荐使用函数式的风格解决break和contine的功能,而不是一个关键字。==

    ~~~~scala
    package com.atguigu.chapter04

    import util.control.Breaks._

    /**
    * @Date 2021/3/23 19:48
    * @Version 10.21
    * @Author DuanChaojie
    */
    object WhileBreak {
    def main(args: Array[String]): Unit = {
    //breakable()函数
    //说明
    //1. breakable 是一个高阶函数:可以接收函数的函数就是高阶函数(后面详解)

    //2. def breakable(op: => Unit) {
    // try {
    // op
    // } catch {
    // case ex: BreakControl =>
    // if (ex ne breakException) throw ex
    // }
    // }
    // (1) op: => Unit 表示接收的参数是一个没有输入,也没有返回值的函数
    // (2) 即可以简单理解可以接收一段代码块
    // 3. breakable 对break()抛出的异常做了处理,代码就继续执行
    // 4. 当我们传入的是代码块,scala程序员会将() 改成{}

    var n = 0
    breakable {
    while (n <= 20) {
    n += 1
    println("n = " + n)
    if (n == 18) {
    break()
    }
    }
    }
    }
    }
    ~~~~

    > 如何实现continue的效果?Scala内置控制结构特地也去掉了continue,是为了更好的适应函数化编程,可以
    >
    > `使用if – else 或是循环守卫实现continue的效果。`

    ~~~~scala
    object ContinueDemo {
    def main(args: Array[String]): Unit = {
    /**
    * 1. 1 to 10
    * 2. 循环守卫 if (i != 2 && i != 3) 这个条件为ture
    * 才执行循环体,即当i ==2 或者 i == 3时,就跳过
    */
    for (i <- 1 to 10 if (i != 2 && i != 3)) {
    println("i=" + i)
    }

    //也可以写成如下的形式
    for (i <- 1 to 10) {
    if (i != 2 && i != 3) {
    println("i=" + i)
    }
    }
    }
    }
    ~~~~

    ## ☆

  • 相关阅读:
    数30的小程序
    convert curl command into java HttpGet
    优秀技术文章转载备份 --- 变速原理
    用 c 调用 win-api 实现自动点击c# winform 程序 的按钮
    win 10 安装 glew 方法
    《想到什么更新什么系列》processing 性能优化
    processing 根据物体移动方向改变朝向
    openFrameworks 无法生成exe已经找不到dll的解决方案
    UE4 无法打开源文件“file_name.generated.h”(Cannot open source file name.generated.h)
    UE4 重新编译老版本的插件
  • 原文地址:https://www.cnblogs.com/huaobin/p/15764409.html
Copyright © 2011-2022 走看看