제어 흐름

jonghwan·2022년 9월 23일
0

멋쟁이사자처럼

목록 보기
11/28
post-thumbnail

스위프트의 제어 흐름

대부분의 프로그래밍 기술은 하나 이상의 조건을 기반으로 결정해가는 코드를 작성하는 것이다.

어떤 코드를 실행할지, 몇 번을 수행할지
이는 프로그램의 흐름을 통제하는 것이므로 제어흐름(control flow)이라고 한다.

일반적으로 제어흐름은 코드를 몇 번 시행할지에 대한 반복 제어(looping control)와 어떤 코드를 실행할지에 대한 조건부 제어 흐름(conditional flow control)으로 나뉜다.

반복 제어 흐름

for-in 반복문

반복문은 지정된 조건에 만족할 때 까지 반복적으로 수행하는 구문이다.

for-in 반복문은 어떤 컬렉션이 숫자 범위에 포함된 일련의 항목들을 반복하는 데 사용한다.

1...5
1..<10

for-in 반복문은 배열이나 딕셔너리 같은 컬렉션을 가지고 작업할 때 특히 더 유용하다.

for 상수명 in 컬렉션 또는 범위 {
  //실행될 코드
}

/*
상수명 (constant name)
반복문이 실행되는 컬렉션 또는 범위의 현재 항목(또는 값)을 담게 될 상수

컬렉션(collection) 또는 범위(range)
문자열들의 배열, 범위 연산자, 문자열 자체 등
*/
for index in 1...5 {
  print("Value of index is \(index)")
}

/*
Value of index is 1
Value of index is 2
Value of index is 3
Value of index is 4
Value of index is 5
*/

현재의 항목을 index라는 이름의 상수에 할당한다.

이 구문에서는 닫힌 연산자 범위를 이용하여 1에서부터 5까지의 숫자 범위로 반복할 것을 선언하고 있다.

반복문 안에서는 index 상수에 할당된 현재(몇 번째) 값을 사용한다.

var integers = [1, 2, 3]
let people = ["ned" : 10, "eric" : 15, "mike" : 12]

for integer in integers {
  print(integer)
}

// Dictionary의 item은 key와 value로 구성된 튜플 타입입니다.
for (name, age) in people {
  print("\(name) : \(age)")
}

현재 항목에 대한 참조체를 저장하기 위해서 상수명을 반드시 선언해야 하는 것은 아니다.

현재 항목에 대한 참조체가 for 반복문 안에서 필요하지 않다면 밑줄 문자로 대체할 수 있다.

var count = 0

for _ in 1...5 {
  // 현재 값에 대한 참조체가 필요없다.
  count += 1
}

while 반복문

for 반복문은 프로그램 내에서 몇 번 반복해야 하는지 알고 있을 때 유용하다.

while 반복문은 어떤 조건에 만족할 때까지 반복해야 하는 코드가 있는데, 그 조건을 충족할 때까지 몇 번 반복해야 하는지를 알 수 없을 경우를 위해 제공된다.

while 반복문은 지정된 조건에 만족할 때까지 일련의 작업을 반복한다.

while 조건문 {
  // 실행될 스위프트 구문  <- 조건문이 true인 동안에 실행될 코드
}
var myCount = 0

while myCount < 100 {
  myCount += 1
}

myCount 변수가 100보다 작은지 평가한다.

만약 100보다 크다면 괄호 안의 코드를 건너뛰고 아무런 작업을 하지 않고 반복문을 종료하게 된다.

myCount 변수가 100보다 크지 않다면 괄호 안의 코드가 실행되며, 프로그램 흐름을 while 구문으로 되돌려서 myCount의 값을 평가하는 작업을 반복하개된다.

이 과정은 myCount의 값이 100보다 작을 때까지 반복되며, 그 순간이 되면 반복문이 종료된다.

repeat-while 반복문

repeat-while 반복문은 Swift 1.x 버전의 do .. while 반복문을 대체한 것이다.

repeat-while 반복문은 while 반복문을 거꾸로 한 것이라고 생각하면 이해하기 쉽다.

while 반복문 : 반복문 안의 코드를 실행하기 전에 표현식을 평가한다.

repeat-while 반복문 : 반복문 안의 코드가 언제나 적어도 한 번은 실행되야 하는 상황을 위해 사용한다.

예를 들어, 배열 안의 항목들 중에 특정 항목을 찾을 때까지 둘러봐야할 경우, 적어도 배열의 첫 번째 항목을 검사해봐야 한다.

repeat {
  // 실행될 스위프트 구문
} while 조건문
var index = 10

repeat {
  index -= 1
} while (index > 0)

반복문에서 빠져나오기

break 구문

반복문을 만들었는데 반복문이 종료되는 조건에 만족하기 전에 어떤 조건에서 반복문을 빠져나와야 할 경우가 있다.

예시 1 - 무한 반복을 만들었을 경우

예시 2 - 네트워크 소켓의 활성화를 지속적으로 점검해야 할 경우, 네트워크 활성화가 감지되면 모니터링하는 반복문에서 빠져나와 다른 작업 실행

break 구문은 반복문에서 빠져나와 반복문 다음의 코드로 이동하여 실행을 계속하게 한다.

var temp = 0

for index in 0..<100 {
  temp += index

  if temp > 100 {
    break
  }

  print("temp = \(temp)")
}

다음번 반복문 처리로 건너뛰기

Continue 구문

continue 구문은 반복문의 나머지 코드를 건너뛰고 반복문의 처음으로 돌아가게 한다.

var index = 1

while index < 20 {
  index += 1

  if (index % 2) != 0 {
    continue
  }
  
  print("index = \(index)")
}

index의 값을 2로 나눈 나머지가 있으면 continue 구문이 실행되어 반복문 안에서 이후 내용을 건너뛰고 while 반복문의 시작 지점으로 돌아가서 (index의 값이 20보다 작을 때까지) 다시 반복문을 수행한다.

index의 값이 짝수일 때만 호출된다.

조건부 흐름 제어

if 구문 사용하기

if 구문은 C, Objective-C, C++, 자바 등 다른 프로그래밍 언어의 if 구문과 유사하다.

Swift if 구문은 다른 프로그램 언어와 다르게, if 구문 안의 실행될 코드가 한 줄이라고 해도, 괄호{ }가 필수다.

기본적으로 조건식(Boolean expression)이 true로 판단되면 구문 내의 코드가 실행된다.

구문내의 코드는 괄호{ }로 묶인다.

조건식이 false로 판단되면 구문 내의 코드는 건너뛴다.

if 조건식 {
  // 조건식이 true일 때 실행될 스위프트 구문
}
let x = 10

if x > 9 {
  print("x is greater than 9!")
}

if ... else ... 구문 사용하기

변형된 if 구문은 if 구문의 조건식이 false로 판단될 때 수행할 코드를 지정할 수 있게 해준다.

if 조건식 {
  // 조건식이 true일 때 실행될 스위프트 구문
} else {
  // 조건식이 false일 때 실행될 스위프트 구문
}
let x = 10

if x > 9 {
  print("x is greater than 9!")
} else {
  print("x is less than 9!")
}

if ... else if ... 구문 사용하기

다양한 조건을 바탕으로 결정해야 할 때 쓸 수 있다.
많은 양의 조건문이 있는 경우에는 번거로울 수 있다. 이런 경우 switch 구문을 활용할 수 있다.

if 조건식1 {
  // 조건식1이 true일 때 실행될 스위프트 구문
} else if 조건식2 {
  // 조건식2이 true일 때 실행될 스위프트 구문
} else if 조건식3 {
  // 조건식3이 true일 때 실행될 스위프트 구문
}
let x = 9

if x == 10 {
  print("x is 10")
} else if x == 9 {
  print("x is 9")
} else if x == 8 {
  print("x is 8")
}
let someInteger = 100

if someInteger < 100 {
  print("100 미만")
} else if someInteger > 100 {
  print("100 초과")
} else {
  print("100")
} // 100

/*
스위프트 조건에는 항상 Bool 타입이 들어와야합니다.
someInteger는 Bool 타입이 아닌 Int 타입이기 때문에 컴파일 오류가 발생합니다
if someInteger {}
*/

guard 구문

guard 구문은 불리언 표현식을 포함하며, true일 때만 guard 구문 다음에 위치한 코드가 실행된다.

guard 구문은 불리언 표현식이 false일 때 수행될 else 절을 반드시 포함해야 한다.

else 절의 코드는 반드시 현재의 코드 흐름에서 빠져나가는 문구(return, break, continue, throw 구문)을 포함한다.

else 블록은 자신을 반환하지 않는 다른 함수나 메서드를 호출할 수도 있다.

기본적으로 guard 구문은 특정 조건을 만족하지 않은 경우게 현재의 함수 또는 반복문에서 빠져나올 수 있게 해준다.

guard 조건문(불리언 표현식) else {
  // 조건문이 false일 때 실행될 스위프트 구문
  <종료구문>
}
func multiplyByTen(value: Int?) {

  guard let number = value, number < 10 else {
    print("Number is too high")
    return
  }

 let result = number * 10
 print(result)
}

switch 구문

Swift의 switch 구문은 다른 프로그래밍 언어와 몇 가지 중요한 차이점이 있다.

if ... else if ... 구문으로 두세개 이상의 조건을 만들 경우 switch 구문이 대안이 될 수 있다.

switch 구문의 표현식(expression)은 값을 가지거나 값을 반환하는 표현식이다. 이 값은 switch 구문이 동작하게 하는 값이다.

그 값과 일치할 수 있는 값을 case 구문으로 제공한다. 각각의 일치하는 값은 표현식의 값과 동일한 타입이어야 한다.

case 조건과 일치하는 값일 경우에 수행될 코드 구문이 case 줄 아래에 작성된다.

default 절은 표현식과 일치하는 case 구문이 없을 경우에 어떻게 해야 하는지를 정의하는 부분이다.

switch 표현식 {
  case 일치하는 값1:
    // 코드구문
  case 일치하는 값2:
    // 코드구문
  case 일치하는 값3, 일치하는 값4:
    // 코드구문
  default:
    // 코드구문
}
let value = 4

switch (value) {
  case 0:
      print("zero")
  case 1:
      print("one")
  case 2:
      print("two")
  case 3:
      print("three")
  case 4:
      print("four")
  case 5:
      print("five")            
  default:
      print("integer out of range")
}

범위 연산자를 활용하면 더욱 쉽고 유용합니다.

switch someInteger {
  case 0:
      print("zero")
  case 1..<100:
      print("1~9")
  case 101...Int.max:
      print("over 100")
  default:
      print("unknown")
}

정수 외의 대부분의 기본 타입을 사용할 수 있습니다.

switch "ned" {
  case "joke":
      print("joke")
  case "mina":
      print("mina")
  case "ned":
      print("ned!!")
  default:
      print("unknown")
}

swich - case 구문 결합하기

각각의 case 구문은 자신만의 실행 코드를 가지고 있다.

하지만 서로 다른 매칭(case)에 대해 동일한 코드가 실행 되어야 하기도 한다.

이러한 경우 각각의 일치하는 경우들을 공통으로 실행될 구문과 묶을 수 있다.

let value = 1

switch (value) {
  case 0, 1, 2:
      print("zero, one or two")
  case 3:
      print("three")
  case 4:
      print("four")
  case 5:
      print("five")         
  default:
      print("integer out of range")
}

switch 구문에서 범위 매칭하기

switch 구문 안에 있는 case 구문에 범위 매칭을 구현 할 수도 있다.

let temperature = 83

switch (temperature) {
  case 0...49:
      print("Cold")
  case 50...79:
      print("Warm")
  case 80...110:
      print("Hot")      
  default:
      print("Temperature out of range")
}

switch - where 구문 사용하기

where 구문은 case 구문에 부가적인 조건을 추가하기 위해서 사용될 수 있다.

let temperature = 54

switch (temperature) {
  case 0...49 where temperature % 2 == 0:
      print("Cold and even")
  case 50...79 where temperature % 2 == 0:
      print("Warm and even")
  case 80...110 where temperature % 2 == 0:
      print("Hot and even")      
  default:
      print("Temperature out of range or odd")
}

값이 범위 조건에 일치하는지 검사할 뿐만 아니라 그 숫자가 홀수인지 짝수인지도 검사한다.

switch - fallthrough 구문 사용하기

case 구문은 break을 쓸 필요가 없다.
다른 언어들과 달리 case 조건에 일치하면 자동으로 구문 밖으로 빠져나간다.

fallthrough 구문을 사용하면 switch 구현부에 예외상황 효과를 주어, 실행 흐름이 그 다음의 case 구문으로 계속 진행하게 할 수 있다.

Swift의 switch 구문에서는 break은 거의 사용되지 않지만, default에서 아무런 작업도 할 필요가 없는 경우에 유용하다.

let temperature = 54

switch (temperature) {
  case 0...49 where temperature % 2 == 0:
      print("Cold and even")
      fallthrough

  case 50...79 where temperature % 2 == 0:
      print("Warm and even")
      fallthrough

  case 80...110 where temperature % 2 == 0:
      print("Hot and even")
      fallthrough   
  default:
      break
}

0개의 댓글