Post

[Kotlin] 4. 프로그램의 흐름 제어

※ “Do it! 코틀린 프로그래밍” 을 참고하여 작성하였습니다.

04-1 조건문

  • 조건문을 한 줄로 구성하기

    1
    
    val max= if (a>b) a else b
    
  • 조건문 블록의 표현식이 길어지면 → 중괄호로 감싸야 함

    • 블록의 마지막 표현식이 변수로 return
    1
    2
    3
    4
    5
    6
    7
    8
    
    val max= if (a>b) {
    		println("a 선택")
    		a
    }
    else{
    		println("b 선택")
    		b
    }
    
  • else if 와 in 연산자의 활용 예

    • else if: 조건문을 중첩하는데 사용
    • in: 변수의 범위 조건을 설정
    1
    2
    3
    4
    5
    6
    7
    
    if (score>=90){
    		grade= 'A'
    } else if (score in 80.0..89.9){
    		grade= 'B'
    } else if (score in 70.0..79.9){
    		grade= 'C'
    }
    
  • when문으로 다양한 조건 처리하기

    • switch-case문과 비슷하다.

    [형식]

    when(인자){

    인자에 일치하는 값 또는 표현식 -> 수행할 문장

    else ->{

    수행할 문장

    }

    }

    • when + 조건식

      • case 1: 조건식에 인자가 활용되지 않는 경우

        1
        2
        3
        4
        
        when(x){
        		parseInt(s) -> print("일치함!")
        		else -> print("기타")
        }
        
      • case 2: 조건식에 in, 범위(…) 연산자가 활용되는 경우

        1
        2
        3
        4
        5
        
        when(x){
        		in 1..10 -> print("x는 1 이상 10 이하입니다")
        		!in 10..20 -> print("x는 10 이상 20 이하의 범위에 포함되지 않습니다")
        		else -> print("x는 어떤 범위에도 없습니다.")
        }
        
      • case 3: 조건식에 is 활용

        1
        2
        3
        4
        5
        
        val str= "안녕하세요"
        val result= when(str){
        		is String -> "문자열입니다."
        		else -> false
        }
        
      • case 4: 인자의 자료형이 Any형인 경우

        1
        2
        3
        4
        5
        6
        7
        
        when(obj){ // obj: Any형
        		1 -> println("Int: $obj")
        		"Hello" -> println("String: $obj")
        		is Long -> println("Long: $obj")
        		!is String -> println("Not a String")
        		else -> println("Unknown")
        }
        

04-2 반복문

  • for 문: in과 범위 지정을 활용한 반복

    1
    2
    3
    4
    
    for (x in 1..5){
    		println(x) // 1, 2, 3, 4, 5
    }
    for (x in 1..5) println(x) // 한 줄로 표현 가능: 1, 2, 3, 4, 5
    
    • 다양한 반복 방법
    1
    2
    3
    4
    5
    6
    
    // 하행(no step)
    for (i in 5 downTo 1) print(i) // 5, 4, 3, 2, 1
      
    // step 만큼 증감
    for (i in 1..5 step 2) print(i) // 1, 3, 5
    for (i in 5 downTo 1 step 2) print(i) // 5, 3, 1
    
  • wihle 문: 조건을 만족하지 않을 때까지 while 문 블록 수행

    [형식]

    while (조건식){

    본문

    }

  • do-while 문: 먼저 do 블록을 실행한 다음, while문의 조건을 검사해서 반복할지를 결정

    [형식]

    do{

    본문

    } while(조건식)

04-3 흐름의 중단과 반환

  • 흐름 제어문과 예외 처리문

    • 흐름 제어문
      • return: 함수에서 결과값을 반환하거나 지정된 라벨로 이동
      • break: for문이나 while문의 조건식에 상관없이 반복문을 끝냄
      • continue: for 문이나 while문의 본문을 모두 수행하지 않고 다시 조건식으로 넘어감
    • 예외 처리문
      • try {…} catch {…}: try 블록의 본문을 수행하는 도중 예외가 발생하면 catch 블록의 본문을 실행
      • try {…} catch {…} finally {…}: 예외가 발생해도 finally 블록 본문은 항상 실행
  • return 문

    • return으로 Unit 반환

      • 반환하는 값: Unit 자료형- 반환 값이 없는 것은 아님
    • 람다식에서 return 사용하기

      • 인라인 함수의 매개변수로 람다식을 사용하면, 람다식에서 return을 사용할 수 있음

        → 이 때, 비지역 반환이 일어날 수 있음

      • 람다식에서 라벨 + return: 비지역 반환 방지

        [형식]

        함수 이름 라벨 이름@{

        return @라벨이름

        }

        … « 여기 부분으로 빠져나감

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        
        fun inlineLambda(a: Int, b: Int, out (Int, Int) -> Unit) {
        	out(a, b)
        } // inline 키워드가 붙지 않음
              
        fun retFunc(){
        		println("start of retFunc")
        		inlineLambda(13, 3) lib@{ a, b ->
        				val result= a+b
        				if (result>10) reeturn@lit
        				println("result: $result") // 실행되지 않음
        		}
        		println("end of retFunc") // 비지역 반환이 방지되므로 해당 출력문 실행
        }
        
      • 암묵적 라벨: 람다식 명칭 그대로 라벨로 사용

        1
        2
        3
        4
        5
        6
        7
        8
        9
        
        fun retFunc(){
        		println("start of retFunc")
        		inlineLambda(13, 3) { a, b ->
        				val result= a+b
        				if (result>10) reeturn@inlineLambda
        				println("result: $result") // 실행되지 않음
        		}
        		println("end of retFunc") // 비지역 반환이 방지되므로 해당 출력문 실행
        }
        
    • 익명 함수를 사용한 반환

      • default: 함수에 람다식 대신, 익명 함수를 사용하여 라벨을 사용하지 않고 동일한 결과를 반환

        1
        2
        3
        4
        5
        6
        7
        8
        9
        
        fun retFunc(){
            println("start of retFunc")
            inlineLambda(13, 3, fun (a, b){
                val result= a+b
                if (result>10) return
                println("result: $result")
            })
            println("end of retFunc")
        }
        
      • 람다식, 익명 함수 방법으로 변수 할당

        → 람다식은 라벨을 사용해야 하고, 마지막 값에 return 키워드를 쓰지 않지만

        → 익명 함수는 라벨을 사용할 필요가 없음

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        
        // 람다식 방법
            var num = 10
            var getMessage = lambda@ { num: Int ->
                if (num !in 1..100) {
                    return@lambda "Error"
                }
                "Success"
            }
            val message = getMessage(num)
            println("getMessage 10: $message")
              
            // 익명 함수 방법
            getMessage= fun(num: Int): String{
                if (num !in 1..100){
                    return "Error"
                }
                return "Success"
            }
            print("getMessage 1000: ")
            println(getMessage(1000))
        
      • 람다식, 익명 함수로 함수를 정의하고, 함수를 호출할 때는 ()()를 두 번 써야 함

  • break, continue 문

    • break + 라벨: for문 앞에 라벨을 붙이면 break했을 때, 라벨의 범위 밖으로 벗어남
    • continue + 라벨: for문 앞에 라벨을 붙이면 continue했을 때, 라벨의 범위로 다시 돌아감
  • 예외 처리

    • 예외: 정상적으로 실행되다가 비정상적으로 프로그램이 종료되는 경우

      • OS의 문제
      • 입력 값의 문제
      • 받아들일 수 없는 연산
      • 메모리의 할당 실패 및 부족
      • 컴퓨터 기계 자체의 문제
    • 형식

      try{

      예외 발생 가능성 있는 문장

      } catch(e: 예외 처리 클래스 이름) {

      예외를 처리하기 위한 문장

      } finally{

      반드시 실행되어야 하는 문장

      }

    • 특정 예외 처리: e → 특정 행위에 대한 예외 클래스 설정 가능

      • 산술 연산의 예외

        1
        2
        3
        4
        5
        
        ...
        } catch(e: ArithmeticException){
        		println("Exception is handled. ${e.message}")
        }
        ...
        
      • 스택의 추적: 임시 메모리 영역인 스택을 추적

        1
        2
        3
        4
        5
        
        ...
        } catch(e: Exception){
        		e.printStackTrace()
        }
        ...
        
    • 예외 발생시키기: 사용자가 특정 조건을 설정하여, 그 조건을 만족하면 예외를 발생시킬 수 있음

      [형식] throw Exception(message: String)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      ...
      		try{
      				...
      				checkAmount(100)
      		} catch (e: Exception){
      				println(e.message)
      		}
      ...
          
      fun checkAmount(amount: Int){
      		if (amount<1000){
      				throw Exception("잔고가 $amount 으로 1000 이하입니다.")
      		}
      }
      
  • 사용자 정의 예외

    [형식] class <사용자 예외="" 클래스="" 이름=""> (message: String): Exception(message)

    • catch(e: 사용자 예외 클래스) { e.message }
    • throw 사용자 예외 클래스(message)
This post is licensed under CC BY 4.0 by the author.