[Swift] 기초 문법 정리 - 조건문과 반복문

Posted by WhiteHyun on February 15, 2022

Goal

  • Swift의 조건문과 반복문을 이해한다.

들어가기에 앞서

  1. 본 글은 Swift의 언어가이드를 따릅니다.[1]
  2. 문법작성규칙은 아래와 같이 작성합니다.[2]
    • lower camel case: method, variable, constant
    • upper camel case: enum, struct, class, extension

조건문

if 구문

  • 대표적인 조건 구문으로 조건의 값이 무조건 Bool 타입이어야 합니다.

    다른 언어의 경우는 정수형을 통해 참 거짓을 구분할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    let first: Int = 5
    let second: Int = 7
    
    if first > second {
      print("first > second")
    } else if first < second {
      print("first < second")
    } else {
      print("first == second")
    }
    

switch 구문

  • 다른 언어와 비교했을 때 상이한 문법 중 하나입니다.

  • case 마다 break를 작성해도 되고 작성하지 않아도 되며, 타 언어와 같이 case를 연속실행하기 위한 트릭을 사용하려면 fallthrough 키워드를 사용하면 됩니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    let integerValue: Int = 5
    
    switch integerValue {
    case 0:
      print("Value == zero")
    case 1...10:
      print("Value == 1~10")
      fallthrough
    case Int.min..<0, 101..<Int.max:
      print("Value < 0 or Value > 100")
      break
    default:
      print("10 < Value <= 100")
    }
    
    // 결과
    // Value == 1~10
    // Value < 0 or Value > 100
    
  • switch 구문 조건에 다양한 값이 들어갈 수 있습니다. 다만 각 case에 들어갈 비교 값은 입력 값과 데이터 타입이 같아야 합니다.
  • 비교될 값이 명확히 한정적인 값(ex. 열거형 등)이 아닐 때는 default를 꼭 작성해줘야 합니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    enum School {
      case primary, elementary, middle, high, college, university, graduate
    }
    
    let academicBackground: School = .university
    
    switch academicBackground {
    case .primary:
      print("최종학력은 유치원입니다.")
    case .elementary:
      print("최종학력은 초등학교입니다.")
    case .middle:
      print("최종학력은 중학교입니다.")
    case .high:
      print("최종학력은 고등학교입니다.")
    case .college, .university:
      print("최종학력은 대학(교)입니다.")
    case .graduate:
      print("최종학력은 대학원입니다.")
    }
    
    // 최종학력은 대학(교)입니다.
    
    • 만약 열거형에 정의한 case에 대해 추가될 여지가 있어 대비하지 못하게 될 수도 있다고 판단될 경우 와일드카드 case(case _)를 사용할 수 있습니다. 허나 문법적으로는 오류가 없지만 논리적 오류가 발생할 수 있기 때문에 unknown속성을 사용하여 컴파일러 경고를 이끌 수 있습니다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      
      enum Menu {
        case chicken, pizza, hamburger
      }
      
      let lunchMenu: Menu = .chicken
      
      switch lunchMenu {
      case .chicken:
        print("양념반 후라이드반")
      case .pizza:
        print("역시 피자는 도미노피자")
      @unknown case _:  // Switch must be exhaustive 경고 발생
        print("메뉴가 뭐죳?")
      }
      
    • 각 case에는 범위 연산자를 사용하거나 where 절을 사용하여 조건을 확장할 수 있습니다.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      
      let position: String = "사원"
      let years: Int = 1
      let isIntern: Bool = false
      
      switch position {
      case "사원" where isIntern == true:
        print("인턴입니다")
      case "사원" where years < 2 && isIntern == false:
        print("신입사원입니다")
      case "사원" where years > 5:
        print("연식 좀 된 사원입니다.")
      case "사원":
        print("사원입니다")
      case "대리":
        print("대리입니다")
      default:
        print("부...장님?")
      }
      
      // 신입사원입니다.
      
  • 정수타입 뿐 아니라 부동소수 타입이나 문자열, 열거형을 튜플, 범위, 패턴이 적용된 타입 등 다양한 타입의 값도 사용 가능합니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    let doubleValue: Double = 3.0
    
    switch doubleValue {
    case 0:
      print("Value == zero")
    case 1.5...10.5:
      print("1.5 <= Value <= 10.5")
    default:
      print("Value == \(doubleValue)")
    }
    
    // 1.5 <= Value <= 10.5
    
    let stringValue: String = "SeungHyeon Hong"
    
    switch stringValue {
    case "Jim Brickman":
      print("He is Jim Brickman")
    case "Minjung Kim":
      print("She is Minjung Kim")
    case "Jenny", "Steve", "Joseb":
      print("He(She) is \(stringValue)")
    default:
      print("\(stringValue) said 'I love Programming ❤️'")
    }
    
    // SeungHyeon Hong said 'I love Programming ❤️'
    
    typealias Resident = (name: String, age: Int)
    
    let tupleValue: Resident = ("SeungHyeon", 100)
    
    switch tupleValue {
    case ("SeungHyeon", 23):
      print("정확히 맞췄습니다!")
    case ("SeungHyeon", _):
      print("이름만 맞았습니다. 나이가 \(tupleValue.age)살이라니..ㅜ")
    case (let name, 23):
      print("나이만 맞았습니다. 이름은 \(name)입니다")
    default:
      print("바보 💩")
    }
    
    // 이름만 맞았습니다. 나이가 100살이라니..ㅜ
    

반복문

for-in 구문

  • 반복적인 데이터나 시퀀스를 다룰 때 많이 사용하는 범위형 반복문입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    
    /*
     * for 임시상수 in 시퀀스 아이템 {
     *   실행코드
     * }
     */
    for i in 0...2 {
      print(i)
    }
    
    for char in "Hello, Swift!" {
      print(char)
    }
    
    var result: Int = 1
    
    // 시퀀스에 해당하는 값이 필요 없다면 와일드카드 식별자(_)를 사용하면 됩니다.
    for _ in 1...3 {
      result += 10
    }
    print("10의 3제곱은 \(result)입니다.")
    
    // Dictionary
    let address: [String: String] = ["도": "경기도", "시군구": "시흥시", "동읍면": "하중동"]
    
    for (key, value) in address {
      print("\(key) : \(value)")
    }
    
    // Set
    let regionNumber: Set<String> = ["02", "031", "032", "033", "041", "042", "043", "051", "052"]
    
    for number in regionNumber {
      print(number)
    }
    

while 구문

  • 다른 프로그래밍 언어 while 구문과 크게 다르지 않습니다.

    1
    2
    3
    4
    5
    6
    
    var names: [String] = ["Minjung", "SeungHyeon", "Jenny", "Yunho"]
    
    while names.isEmpty == false {
      print("Good bye \(names.removeFirst())")
      // removeFirst(): 첫 번째 요소를 삭제함과 동시에 삭제한 요소 반환
    }
    

repeat-while 구문

  • 다른 프로그래밍 언어의 do-while 구문과 크게 다르지 않습니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    var names: [String] = ["Minjung", "SeungHyeon", "Jenny", "Yunho"]
    
    repeat {
      print("\(names.removeFirst())")
      // removeFirst(): 첫 번째 요소를 삭제함과 동시에 삭제한 요소 반환
    } while names.isEmpty == false
    // Prints "Minjung"
    // "SeungHyeon"
    // "Jenny"
    // "Yunho"
    

구문 이름표

  • 중첩 반복문을 작성하게 될 때 큰 범위의 반복문을 종료하고 싶거나 반복문을 제어하는 키워드(break, continue, etc)가 어떤 범위에 적용돼야 하는지 애매할 경우 사용합니다.
  • 반복문 앞에 이름과 콜론을 붙여 구문의 이름을 지정해주는 구문 이름표를 사용합니다. 이름이 지정된 구문을 제어하고자 할 때는 제어 키워드와 구문 이름을 함께 써주면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var numbers: [Int] = [3, 2342, 6, 3252]

numbersLoop: for num in numbers {
  if num > 5 || num < 1 {
    continue numbersLoop
  }

  var count: Int = 0

  printLoop: while true {
    print(num)
    count += 1

    if count == num {
      break printLoop
    }
  }

  removeLoop: while true {
    if numbers.first != num {
      break numbersLoop
    }
    numbers.removeFirst()
  }
}

// 3
// 3
// 3
// numbers에 [2342, 6, 3252]가 남습니다.

Reference

  1. The Basics — The Swift Programming Language (Swift 5.6)
  2. Camel Case - 위키피디아