06. 흐름 제어

JinStory77·2022년 5월 12일
0

Swift 공부_기초

목록 보기
6/11

흐름 제어

  • 특정 조건에서 코드를 실행해야 하는 상황, 실행하지 말아야 하는 상황, 특정 명령어를 반복해서 실행해야 하는 상황도 발생한다. 이럴때 사용하는 것이 조건문과 반복문이다.


1. 조건문

  • if 구문, switch 구문이 있다.

1.1. if 구문

  • if, else 등의 키워드를 사용하며 스위프트의 if 구문은 조건의 값이 꼭 Bool 타입이어야 한다.
    • 정수, 실수 등 0이 아닌 모든 값을 참으로 취급하지 않는다는 말이다.
  • else if는 갯수가 상관없이 가능, else는 마지막에 한번만 가능
  • 위에서 조건을 충족하면 이어진 구문의 조건에 충족하더라도 실행되지 않고 조건문을 빠져나온다.
  • if 키워드에 뒤에 조건수식을 소괄호(())로 감싸주는건 선택사항이다.

  • if 구문 기본 표현
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")
}
// first < second

  • if 구문의 다양한 구현(소괄호가 없는 코드)
let first: Int = 5
let second: Int = 5
var biggerValue: Int = 0

if first > second {
    biggerValue = first
} else if first == second {
    biggerValue = first             // 5
// 조건 충족됨, 다음 조건들 부터는 충족하더라도 이미 first == second 라는 조건이 먼저 충족돼 다음 조건은 실행되지 않음
} else if first < second {
    biggerValue = second
} else if first == 5 {
    biggerValue = 100
}

  • if 구문의 다양한 구현(소괄호가 있는 코드)
let first: Int = 5
let second: Int = 5
var biggerValue: Int = 0

if (first > second) {
    biggerValue = first
} else if (first == second) {
    biggerValue = first
// 조건 충족됨, 다음 조건들 부터는 충족하더라도 이미 first == second 라는 조건이 먼저 충족돼 다음 조건은 실행되지 않음
} else if (first < second) {
    biggerValue = second
} else if (first == 5) {
    biggerValue = 100
}
print(biggerValue)

1.2. switch 구문

  • switch 구문도 소괄호(()) 생략 가능하다.
  • break 키워드는 선택 사항이다.
    • case 내부의 코드를 모두 실행하면 break 없이도 switch 구문이 종료된다는 뜻이다. 따라서 break를 쓰지 않고 case를 연속 실행하던 트릭은 더 이상 사용 불가하다.
    • 스위프트에서 switch 구문의 case를 연속 실행하려면(break되는 것을 무시하려면) fallthrough 키워드를 사용한다. 원하는 만큼 여러번 사용가능하다.
  • 매우 한정적인 값(enum, case 등)이 비교 값이 아니면 default를 꼭 작성해줘야 한다.
  • switch 구문의 조건에 다양한 값이 들어갈 수 있으나 case에 들어갈 비교 값은 입력 값과 데이터 타임이 같아야 한다.
  • case에는 범위 연산자를 사용할 수도, where 절을 사용하여 조건을 확장할 수도 있다.

  • switch 구문 기본 표현
switch 입력 값 {
  case 비교 값 1:
      실행 구문
  case 비교 값 2:
      실행 구문
      // 이번 case를 마치고 switch 구문을 탈출하지 않는다. 아래 case로 넘어간다.
      fallthrough
  case 비교 값 3, 비교 값 4, 비교 값 5:  // 한 번에 여러 값을 비교할 수 있다.
      실행 구문
      break                // break 키워드를 통한 종료는 선택 사항이다.
  default:                 // 한정된 범위가 명확하지 않다면 default는 필수이다.
      실행 구문
}
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 구성
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

  • 문자열 switch case 구성
let stringValue: String = "Liam neeson"

switch stringValue {
case "Jin":
    print("He is Jin")
case "Jay":
    print("He is Jay")
case "Jenny", "Joker", "Nova":
    print("He or She is \(stringValue)")
default:
    print("\(stringValue) said 'I don't know who you are'")
}

// Liam Neeson said 'I don't know who you are'
  • 잘못된 case 사용
case "Jenny":
// stringValue가 "Jenny"에 해당할 때 실행될 코드가 있어야 함. 없어서 에러 뜸.

  • fallthrough의 사용
let stringValue: String = "Joker"

switch stringValue {
case "Jin":
    print("He is Jin")
case "Jay":
    print("He is Jay")
case "Jenny":
    fallthrough                     // fallthrough라 계속 진행
case "Joker":
    fallthrough                     // fallthrough라 계속 진행
case "Nova":
    print("He or She is \(stringValue)")   // 여기서 결과가 나옴
default:
    print("\(stringValue) said 'I don't know who you are'")
}
// He or She is joker

✏️ if문을 switch문으로 바꿔보기

  • if문
func loveCalculator() {
    let loveScore = Int.random(in: 0...100)

    if loveScore > 80 {
        print("당신은 서로 많이 사랑합니다.")
    } else if loveScore > 40 && loveScore <= 80  {
        print("당신은 썸을 타고 있습니다.")
    } else {
        print("당신은 평생 혼자입니다..")
    }
}
loveCalculator()

  • switch문
func loveCalculator() {
    let loveScore = Int.random(in: 0...100)
    
switch loveScore {
    case 81...100:
      print("당신은 서로 많이 사랑합니다.")
    case 41..<81:
      print("당신은 썸을 타고 있습니다.")
    case ...40:
      print("당신은 평생 혼자입니다..")
    default:
      print("다시 실행해주세요")
    }
}
loveCalculator()

  • 튜플 switch case 구성
typealias NameAge = (name: String, age: Int)

let tupleValue: NameAge = ("Jin", 28)

switch tupleValue {
case ("Jin", 50):
    print("정확히 맞췄습니다!")
default:
    print("누굴 찾나요?")
}
// 누굴 찾나요?

  • 와일드카드 식별자(_)를 사용한 튜플 switch case 구성
typealias NameAge = (name: String, age: Int)

let tupleValue: NameAge = ("Jin", 99)

switch tupleValue {
case ("Jin", 28):
    print("정확히 맞췄습니다!")
case ("Jin", _):
    print("이름만 맞았습니다. 나이는 \(tupleValue.age)입니다.")
case (_, 28):
            print("나이만 맞았습니다. 이름은 \(tupleValue.name)입니다.")
default:
    print("누굴 찾나요?")
}

  • 값 바인딩을 사용한 튜플 switch case 구성
typealias NameAge = (name: String, age: Int)

let tupleValue: NameAge = ("Jin", 99)

switch tupleValue {
case ("Jin", 28):
    print("정확히 맞췄습니다!")
case ("Jin", let age):
    print("이름만 맞았습니다. 나이는 \(tupleValue.age)입니다.")
case (let name, 28):
    print("나이만 맞았습니다. 이름은 \(tupleValue.name)입니다.")
default:
    print("누굴 찾나요?")
}
// 이름만 맞았습니다. 나이는 99입니다

  • where를 사용하여 switch case 확장
let 직급: String = "사원"
let 연차: Int = 1
let 인턴인가: Bool = false

switch 직급 {
case "사원" where 인턴인가 == true:
    print("인턴입니다.")
case "사원" where 연차 < 2 && 인턴인가 == false:
    print("신입사원입니다.")
case "사원" where 연차 > 5:
    print("연식 좀 된 사원입니다.")
case "사원":
    print("사원입니다.")
case "대리":
    print("대리입니다.")
default:
    print("사장입니까?")
}

  • 열거형을 입력 값으로 받는 switch 구문
enum School {
    case primary, elementary, middle, high, university
}

let 최종학력: School = School.university

switch 최종학력 {
case .primary:
    print("최종학력은 유치원입니다.")
case .elementary:
    print("최종학력은 초등학교생압니다.")
case .middle:
    print("최종학력은 중학교입니다.")
case .high:
    print("최종학력은 고등학교입니다.")
case .university:
    print("최종학력은 대학교입니다.")
}
// 최종학력은 대학교입니다.

  • Menu 열거형의 모든 case 처리하는 switch 구문의 상태
enum Menu {
    case chicken
    case pizza
}

let lunchMenu: Menu = .chicken

switch lunchMenu {
case .chicken:
    print("반반 무많이")
case .pizza:
    print("핫소스 많이 주세요")
case _:         // case default: 와 같은 표현입니다.
    print("오늘 메뉴가 뭐죠?")
}

  • 차후에 Menu 열거형에 추가한 case를 처리하지 않으면 경고를 내어줄 unknown 속성
enum Menu {
    case chicken
    case pizza
    case hamburger
}

let lunchMenu: Menu = .chicken

switch lunchMenu {
case .chicken:
    print("반반 무많이")
case .pizza:
    print("핫소스 많이 주세요")
@unknown case _:
    print("오늘 메뉴가 뭐죠?")
}


2. 반복문

  • 배열과 같은 시퀀스, 순서가 있는 데이터는 반복문으로 편하게 처리 할 수 있다.

2.1. for-in 구문

  • for-in 반복 구문은 반복적인 데이터나 시퀀스를 다룰 때 사용한다.
  • for '상수' in ( )...( )
for 임시 상수 in 시퀀스 아이템 {
실행코드
}
for _ in 1...5 {
    print("play")
}
// play를 5번 출력함

// +=
var aa: Int = 4
for _ in 1...3{
     aa += 2
}
print(aa)

// *=
var ab: Int = 9
for _ in 1...3{
     ab *= 3
}
print(ab)

// /=
var ac: Double = 300
for _ in 1...3{
     ac /= 5
}
print(ac)
// for-in 반복 구문의 활용
for i in 0...2 {
    print(i)
}

for i in 0...5 {
    if i.isMultiple(of: 2){
        print(i)
        continue    //continue 키워드를 사용하면 바로 다음 시퀀스로 건너뜀
    }
     print("\(i) == 홀수")
}

//-------------


let helloSwift: String = "Hello Swift!"

for char in helloSwift {
        print(char)
}

//-------------

//
var result: Int = 1

for _ in 1...3 {
    result *= 10
}
// 시퀀스에 해당하는 값이 필요없다면 와일드 카드 식별자(_)를 사용하면 됨

print("10의 3제곱은 \(result)입니다.")
// 10의 3제곱은 1000입니다

  • 기본 데이터 타입의 for-in 반복 구문 사용
// Dictionay
let friends: [String: Int] = ["Jay": 35, "Joe": 29, "Jenny": 31]

for tuple in friends {
    print(tuple)
}
/* (key: "Jay", value: 35)
(key: "Joe", value: 29)
(key: "Jenny", value: 31) */

// ------------
let 주소: [String: String] =
["도": "충청북도", "시군구": "청주시 청원구", "동읍면": "율량동"]

for (,) in 주소 {
    print("\() : \()")
}
/* 동읍면 : 율량동
도 : 충청북도
시군구 : 청주시 청원구 */

// -------------
let 지역번호: Set<String> = ["02", "031", "032", "033"]

for 번호 in 지역번호 {
    print(번호)
}
//02 //031 //032 //033
// 나혼자 연습노트
for _ in 1...3 {
    var aab: String = "나는 개발자다!"
    print(aab)
}

for _ in 1...3 {
    print("나는 개발자다!")
}

2.2. while 구문

  • 특정 조건(Bool 타입)이 성립하는 한 블록 내부의 코드를 반복해서 실행한다.
  • for-in 구문과 마간가지로 continue, break 등의 제어 키워드 사용이 가능하다.

  • while 반복 구문의 사용
var names: [String] = ["Joker", "Jenny", "Nova", "Jin"]

while names.isEmpty == false {
    print("Good bye \(names.removeFirst())")
    // removeFirst()는 요소를 삭제함과 동시에 삭제한 요소를 반환
}
//Good bye Joker, //Good bye Jenny, //Good bye Nova, //Good bye Jin
var count = 3

print("Ready!")

while count > 0 {
    print("\(count)...")     // 조건 수행한다는 뜻
    count -= 1
}
// 3부터 count가 0보다 클때까지만(조건) 안에 있는 코드들을 반복
print("START!")
/* Ready!
3...
2...
1...
START! */

  • while 구문을 if 구문으로 바꿨을 경우
var count = 3

print("Ready!")

if count > 0 {
    print("\(count)...")     // 조건 / {}안에 있는 코드들을 반복 수행한다는 뜻
    count -= 1

print("START!")
/* Ready!
3...
START! */

2.3. repeat-while 구문

  • repeat 블록의 코드를 최초 1회 실행 후, while 다음의 조건이 성립하면 블록 내부의 코드를 반복 실행한다.

  • repeat-while 반복 구문의 사용
var names: [String] = ["John", "Jenny", "Joe", "Jin"]

repeat {
    print("Good bye \(names.removeFirst())")
    // removeFirst()는 요소를 삭제함과 동시에 삭제한 요소를 반환
} while names.isEmpty == false
            
// Good bye John //Good bye Jenny //Good bye Joe //Good bye Jin


3. 구문 이름표

  • 중첩된 반복문을 사용할 때 지정된 구문을 제어하고자 할 때는 제어 키워드와 구문 이름을 할 때 사용한다.

  • 중첩된 반복문의 구문 이름표 사용
var numbers: [Int] = [3, 2343, 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()
        }
}
profile
Let's smile for future 🤩

0개의 댓글