[TIL] 프로그램의 흐름제어

28903 단어 TILTIL_KotlinTIL

Do it! 코틀린 프로그래밍 [첫째마당, 코틀린 기본 익히기] 학습

✏️1. 조건문✏️

주어진 조건에 따라 다른 결과를 반환하는 코드


1-1. if문과 if~else문

⬇️ if~else문의 구조

if (조건식) {
	수행할 문장
} else {
	수행할 문장
}

📌 수행할 문장이 하나인 경우에는 중괄호({}) 생략 가능

if (조건식) 수행할 문장
else 수행할 문장

📌 조건문의 표현식

  • 조건문 블록의 표현식이 길어지면 중괄호로 감싸고, 블록의 마지막 표현식이 변수에 반환되어 할당
val max = if(a > b) {
	println("a")
    a // return a -> a가 max에 할당 
} else {
	println("b")
    b // return b -> b가 max에 할당
}

1-2. in 연산자와 범위 연산자

📌 in 연산자와 범위 연산자(..)

  • 포함 여부 확인을 위한 연산자
  • 변수 이름 in 시작값..마지막값
  • score in 80..89 -> 범위에 80과 89도 포함

1-3. when문

📌 인자를 사용하는 when 문

when (인자) {
	인자에 일치하는 값 혹은 표현식 -> 수행할 문장
    인자에 일치하는 범위 -> 수행할 문장
    0,1 -> 수행할 문장 // (1) 조건이 여러개인 경우
    parseInt(s) -> 수행할 문장 // (2) 함수의 반환값을 조건으로 사용
    in 1..10 -> 수행할 문장 // (3) in연산자와 범위 지정자 사용
    !in 1..10 -> 수행할 문장 // (4) !사용
    is String -> 수행할 문장 // (5) is 키워드 사용
    ...
    else -> 수행할 문장
}
  • (1) 일치되는 조건을 한 번에 여러 개 표현하려면 쉼표(,)를 이용
  • (2) 함수의 반환값을 조건에 사용할 수 있음
  • (3) in 연산자, 범위 지정자를 통해 인자가 범위에 포함되는지 검사
  • (4) !를 사용하면 해당 범위 이외의 요소를 가르킴. 즉 1~10 이외의 범위를 나타냄
  • (5) 자료형을 검사하여 자료형에 따라 문장을 실행

📌 인자를 사용하지 않는 when 문

when {
	조건 혹은 표현식 -> 실행할 문장
    ...
}

⬇️ 인자를 사용하지 않는 when문 예시

when {
	score >= 90.0 -> grade = 'A'
    score in 80.0..89.9 -> grade = 'B'
    ...
}

📌 다양한 자료형의 인자 받기

  • when의 인자로 Any를 사용하면 다양한 자료형의 인자를 받을 수 있음
fun case(obj: Any) {
	when(obj) {
    	1 -> println("Int: $obj")
        "Hello" -> println("String: $obj")
        is Long -> println("Long: $obj")
        else -> println("Unknown")
    }
}

✏️2. 반복문✏️

블록 안에 있는 코드를 반복하여 실행하는 명령문


2-1. for문

for문은 내부적으로 반복을 처리하는 인터페이스인 이터레이터(Iterator)에 의해 배열이나 특정 값의 범위, 컬렉션으로 불리는 요소 등에서 사용 가능

📌 for문의 기본형

  • for(요소 변수 in 컬렉션 또는 범위) { 반복할 본문 }
  • for문의 블록 내용이 한줄이라면 중괄호({}) 생략 가능
/* 기본형 예시 */
for(x in 1..5) {   
	println(x)
}

/* 중괄호({}) 생략 */
for(x in 1..5) println(x) 

📌 하행 for 문

  • downTo 키워드 사용
  • for (i in 5 downTo 1) print(i)

📌 n단계씩 증가

  • step 키워드 사용
  • for (i in 1..5 step 2) print(i) -> 2단계씩 증가
  • for (i in 5 downTo 1 step 2) print(i) -> 2단계씩 하행

2-2. while문

while문은 조건식이 true를 만족하는 경우 while문의 블록을 무한히 반복. 조건식이 false가 되면 실행문이 중단되어 while 루프를 빠져나감

⬇️ while문의 형식

while(조건식) {
	본문
    ....
}

📌 do~while문

  • do 블록에 작성한 본문을 한 번은 실행한 다음 마지막에 조건식을 검사하여 true가 나오면 작업을 반복

⬇️ do~while문의 형식

do {
	본문
} while (조건식)

📍 while문은 데몬 프로그램을 만들 때 쓰이기도 함

  • 데몬(daemon)이란? 백그라운드에서 실행하면서 종료되지 않고 지속적으로 무엇인가를 처리하는 프로그램

✏️3. 흐름의 중단과 반환✏️

3-1. return 문

함수에서 결괏값을 반환하거나 지정된 라벨로 이동함

📌 return으로 Unit 반환하기

/* Unit을 명시적으로 반환 */
fun hello(name: String): Unit{
	println(name)
    return Unit
}

/* Unit 이름을 생략한 반환 */
fun hello(name: String): Unit{
	println(name)
    return
}

/* return문 자체를 생략 */
fun hello(name: String){
	println(name)
}
  • 위의 세 방법은 모두 동일한 결과를 반환
  • 세번째 코드처럼 Unit과 return을 생략할 경우 코틀린 컴파일러는 Unit을 반환하는 것으로 가정

📍 람다식에서 return은 라벨 표기와 함께 사용해야 하고 break, continue는 아직 지원되지 않음

📌 inline으로 선언된 람다식에서 return 사용하기

  • inline으로 선언된 함수에서 람다식을 매개변수로 사용하면 람다식에서 return 가용 가능
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 // return시 (1)로 빠져나감
        println("result: $result")
    }
    println("end of retFunc") // 실행 X
} // (1)

📌 inline으로 선언되지 않은 람다식에서 return 사용하기

  • return@label 과 같이 라벨(label)표기와 함께 사용해야 함
  • 라벨(label) : 특정한 위치를 임의로 표시한 것. @기호와 붙여서 사용
  • 라벨 사용시 가장 가까운 함수로 빠져나감

⬇️ 람다식과 라벨기호 사용 형식

람다식 함수 이름 라벨 이름@{
	...
    return@라벨이름
}

⬇️ 라벨을 사용한 람다식의 변환

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

fun retFunc() {
	println("start of retFunc")
    lambdaExample(13, 3) lit@{a, b ->
    	val result = a + b
        if(result > 10) return@lit// return시 (1)로 빠져나감
        println("result: $result")
    } // (1) 가장 가까운 retFunc()로 빠져나감
    println("end of retFunc") // 실행 O
} 

📌 암묵적 라벨

  • 람다식의 명칭을 그대로 라벨처럼 사용
fun retFunc() {
	println("start of retFunc")
    lambdaExample(13, 3) lit@{a, b ->
    	val result = a + b
        if(result > 10) return@lambdaExample // (1)로 빠져나감
        println("result: $result")
    } // (1) 가장 가까운 retFunc()로 빠져나감
    println("end of retFunc") // 실행 O
} 

📌 익명 함수를 사용한 반환

  • 익명 함수는 일반 함수처럼 작동하기 때문에 라벨을 사용하지 않고도 가까운 익명 함수 자체가 반환됨
fun retFunc() {
	println("start of retFunc")
    lambdaExample(13, 3, fun(a, b) { 
    	val result = a + b
        if(result > 10) return // (1)로 빠져나감
        println("result: $result")
    }) // (1) lambdaExample() 의 끝부분
    println("end of retFunc") // 실행 O
} 

📍 람다식과 익명 함수를 함수에 할당할 때 주의할 점

  • fun greet() = { println("Hello") }
  • fun greet() = fun() { println("Hello") }
    -> 익명 함수를 사용하여 함수가 할당됨을 명시적으로 표현하여 읽기에 더 좋음
  • greet() -> 아무것도 출력되지 않음
  • greet()() -> greet() 함수가 가지고 있는 함수를 사용 Hello 출력

3-2. break 와 continue

📌 break문

  • break를 사용한 지점에서 for나 while문 루프를 빠져나옴
for(반복 조건) {
	...
	if(중단 조건) {
    	break // for문 밖 (1)로 빠져나감
    }
    ...
} // (1)

📌 continue문

  • continue 이후 본문을 계속 진행하지 않고 반복 조건으로 돌아감
for(반복 조건) { // (1)
	...
	if(중단 조건) {
    	break // for문의 반복 조건(1)로 돌아감
    }
    ...
} 

📌 break와 continue에 라벨 함께 사용하기

⬇️ 라벨 없이 break

for(i in 1..5) {
	second@ for (j in 1..5){
     	if(j == 3) break // (1)로 빠져나감
    } // (1)
}

⬇️ 라벨을 사용하여 break (return@first)

first@ for(i in 1..5) {
	second@ for (j in 1..5) {
    	if(j == 3) break@first // (1)로 빠져나감
    }
} // (1) first블럭의 끝 

3-3. 예외 처리

  • 예외(Exception) : 코드가 제대로 작동하지 못하고 중단되는 현상
  • 대부분의 오류는 코드를 작성하는 도중 컴파일러가 잡아낼 수 있으나, 메무리 부족이나 파일이 손상되는 등의 실행 도중의 잠재적인 오류까지는 검사할 수 없음

📌 예외를 발생시키는 상황

  • 운영체제의 문제(잘못된 시스템 호출의 문제)
  • 입력값의 문제(존재하지 않는 파일 또는 숫자 입력란에 문자 입력 등)
  • 받아들일 수 없는 연산(0으로 나누기 등)
  • 메모리의 할당 실패 및 부족
  • 컴퓨터 기계 자체의 문제(전원 문제, 망가진 기억 장치 등)

📌 try-catch

try {
	예외 발생 가능성 있는 문장
} catch(e: 예외 처리 클래스 이름) { 
	예외를 처리하기 위한 문장
} finally {
	반드시 실행되어야 하는 문장
}
  • try 블록에서 예외가 발생하면 catch 블록에서 잡아서 예외를 처리
  • catch 예외가 없어 처리할 수 없으면 프로그램 중단
  • finally 블록은 try 블록의 예외 발생 여부에 상관없이 반드시 처리되어야 하는 문장을 작성
    -> try블록에서 '파일 열기' 작업을 작성했다면 finally 블록에서는 '파일 닫기' 작업을 작성

📌 예외 발생시키기 (throw)

  • 의도적으로 예외를 발생시킬 수 있음
  • throw Exception(message: String)
  • throw로 예외를 발생시키면 catch가 잡아서 처리

📌 사용자 정의 예외

  • 기본 Exception 클래스로부터 새롭게 사용자가 정의한 예외 클래스를 만들 수 있음
  • class <사용자 예외 클래스 이름>(message: String) : Exception(message)
  • catch(e: 사용자 예외 클래스 이름) { e.message }

📍 ArithmeticException, IOException, ClassNotFoundException 등의 예외클래스를 제공하고 이들 클래스는 Throwable 클래스의 자식 클래스임

좋은 웹페이지 즐겨찾기