상세 컨텐츠

본문 제목

4주차 - 프로그램의 흐름 제어

책 리뷰/Do it! 코틀린 프로그래밍

by 근성 2024. 1. 4. 22:56

본문

본 책에서 제어는 크게 3가지가 있다.

조건문, 반복문, 흐름의 중단과 반환


조건문

코틀린은 조건문이 다른언어들에 비해서 간략하게 사용할 수 있는 표현들이 많다.

그래서 기존 습관을 버리고 간략화된 표현을 쓰도록 노력해야한다.

 

예를 들어 최댓값을 구하는 식을 한줄로 표현할 수 있는데, 한줄이다보니 가독성도 좋고 간단해 보인다. 

val max = if (a > b) a else b

 

if절이 길어진 경우에도 한번 보자. 

package chap04.section1

fun main() {
    val a = 12
    val b = 7

    val max = if (a > b){
        println("a 선택")
        a
    }
    else{
        println("b 선택")
        b
    }

    println(max)
}

if와 else절 안에 a, b 딸랑 하나만 나오는 경우가 있어서 신기했다. (못알아볼뻔했다.)

 

in

조건중에 80 이상 89.9 이하를 아래와 같이 표현할 수 있다.

변수이름 in 시작값..마지막값 으로 나타낼 수 있다.

아래를 참고하자.

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

언뜻봐서는 C언어의 switch와 느낌이 비슷하다.

package chap04.section1

fun main() {
    print("Enter the score: ")
    val score = readLine()!!.toDouble()
    var grade: Char = 'F'

    when (score){
        in 90.0..100.0 -> grade = 'A'
        in 80.0..89.9 -> grade = 'B'
        in 70.0..79.9 -> grade = 'C'
        !in 70.0..100.0->grade = 'F'
    }
    println("Score: $score, Grade: $grade")
}

IntelliJ에서 in 구문을 작성하면 부등호가 표시된다. 너무 신기하다.

Any를 통해서도 when문을 사용할 수 있다.

package chap04.section1

fun main() {
    cases("Hello")
    cases(1)
    cases(System.currentTimeMillis())
}

fun cases(obj: Any){
    when(obj){
        1 -> println("Int: $obj")
        "Hello" -> println("String: $obj")
        is Long -> println("Long: $obj")
        !is String -> println("Not a String")
        else -> println("Unknown")
    }
}

 

 

 


반복문

 

반복문도 간단해보인다. in과 .. 조건문에서 범위로 봤던것이다.

for (x in 1..5) {
	print(x)
}

 

파이썬과 비슷한 형태도 있다. 

// kotlin
for (i in 1..5 step 2) print(i)
# python
for i in range(1, 5, 2):
	print(i)

 

5부터 1까지 떨어뜨리고 싶을때는 downTo 키워드를 사용한다.

for (i in 5 downTo 1) print(i)

 

히스토그램을 한번 찍어보자

package chap04.section2

fun main() {
    print("Enter the lines: ")
    val n = readLine()!!.toInt()

    for (line in 1..n){
        for (space in 1..(n - line)) print(" ")
        for (star in 1..(2 * line - 1)) print("*")
        println()
    }
}

while문과 do while문은 기존과 비슷하니 넘어가겠다.

 


흐름의 중단과 반환

 

inline을 사용한 람다식의 반환이 있다.

inline으로 선언되지 않은 람다식에서 return을 그냥 사용할 수 없고, return@label과 같이 라벨을 표기해야한다.

인라인으로 선언된 함수에서 람다식을 매개변수로 사용하면 람다식에서 return을 사용할 수 있다.

 

아래 코드는 label이 없기에 바로 retFunc를 탈출한다.

package chap04.section3

fun main() {
    retFunc()
}

inline fun inlineLambda(a: Int, b: Int, out: (Int, Int) -> Unit){
    out(a, b)
}

fun retFunc() {
    println("start of retFunc")
    inlineLambda(13, 3){ a, b ->
        val result = a + b
        if(result > 10) return
        println("result: $result")
    }
    println("end of retFunc")
}

 

라벨을 쓰는 경우를 한번 살펴보자

package chap04.section3.noinline

fun main() {
    retFunc()
}

fun inlineLambda(a: Int, b: Int, out: (Int, Int) -> Unit){ // Inline을 제거
    out(a, b)
}

fun retFunc() {
    println("start of retFunc")
    inlineLambda(13, 3)lit@{ a, b -> // 람다식 블록의 시작 부분에 라벨을 지정
        val result = a + b
        if(result > 10) return@lit // 라벨을 사용한 블록의 끝부분으로 반환
        println("result: $result")
    } // 이 부분으로 빠져나감
    println("end of retFunc") // 이 부분이 실행
}

label을 사용하는 경우 잘 빠져나가는 것을 볼 수 있다.

 

 

try catch도 사용해보자.

아래 예시는 0으로 나누는 경우이다.

package chap04.section3

fun main() {
    val a = 6
    val b = 0
    val c : Int

    try {
        c = a / b // 0으로 나눔
    } catch (e: Exception){
        println("Exception is handled.")
    } finally{
        println("finally 블록은 반드시 항상 실행됨")
    }
}

 

throw를 통해 예외를 발생시킬 수 있다.

package chap04.section3

fun main() {
    var amount = 600

    try{
        amount -= 100
        checkAmount(amount)
    } catch (e: Exception){
        println(e.message)
    }
    println("amount: $amount")
}

fun checkAmount(amount: Int){
    if (amount < 1000)
        throw Exception("잔고가 $amount 으로 1000이하입니다.")
}

 

사용자 정의 예외를 직접 만들 수도 있다.

아래 코드는 InvalidNameException이라는 클래스를 직접 선언한 경우이다.

package chap04.section3

class InvalidNameException(message: String) : Exception(message) // 사용자 예외 클래스

fun main() {
    var name = "kildong123"

    try{
        validateName(name)
    }catch (e : InvalidNameException){
        println(e.message)
    } catch (e: Exception) { // 기타 예외 처리
        println(e.message)
    }
}

fun validateName(name : String){
    if(name.matches(Regex(".*\\d+.*"))){ // 이름에 숫자가 포함되어 있으면 예외 발생시킴
        throw InvalidNameException("Your name : $name : contains numerals.")
    }
}

관련글 더보기

댓글 영역