본문 바로가기

학습 노트/Swift (2021)

032 ~ 036. Conditional Statements (조건문)

if Statement (if 문)

Statement

if condition {
    statements
}
let id = "root"
let password = "1234qwer"

//id 확인
if id == "root" {
    print("valid id")
}

//password 확인
if password == "1234qwer" {
    print("valid password")
}

 

결과

valid id
valid password

두 가지의 조건문을 논리 연산을 통해 하나로 묶을 수도 있다.

let id = "root"
let password = "1234qwer"

if id == "root" && password == "1234qwer" {
    ("login success")
}
결과

login success

다른 조건을 추가하고 싶은 경우 else if와 else문을 사용하여 구현 가능하다.

Statement

if condition1 {
    statments
} else if condition2 {
    statments
} else {
    statments
}
let id = "root"
let password = "1234qwer"

if id != "root" {
    print("wrong id")
} else if password != "1234qwer" {
    print("wrong password")
} else {
    print("login success")
}

 

결과

login success

또한 if문 내에 if문을 사용하는 것도 가능하다.

let num = 7

if num >= 0 {
    print("positive number or zero")
    if num % 2 == 0 {
        print("positive even number")
    } else {
        print("positive odd number")
    }
}  else {
    print("negative number")
}

 

결과

positive number of zero
positive odd number

단, 조건을 여러번 판단하기 위해 주의해야 할 점이 있다.

let num = 200

if num > 0 {
    print("number over zero")
} else if num > 100{
    print("number over 100")
}
결과

number over zero

if문의 경우 조건을 비교하다 성립하게 되면 이하의 조건들을 상관하지 않고 if문을 종료한다.
따라서 '더 작은 개념의 조건'을 먼저 비교한 후 추가적인 조건들을 비교하거나 다른 조건문을 고려하는 것이 용이할 수 있다.

let num = 10

if num > 100 {
    print("number over 100")
} else if num > 0{
    print("number over zero")
}

 

결과

number over zero

 

Switch Statement (스위치 문)

Pattern Matching, Value Matching

Statement

switch valueExpression:
case pattern:
    statements
case pattern, pattern:
    statements
default:
    statements
}
let num = 7

switch num {
case 1:
   print("one")
case 2, 3:
   print("two or three")
default:
   print("others")
}

 

결과

others

예상 결과에 따른 분기에는 굉장히 간편하지만
한 가지의 변수에만 대응할 수 있다는 단점이 있다.

또한 switch문은 모든 경우를 고려해야 한다.
따라서 default를 항상 사용해야 하며, 별도의 동작을 원치 않을 경우 'break'을 사용하도록 한다.

let num = 7

switch num {
case 1:
   print("one")
case 2, 3:
   print("two or three")
default:
   break
}

 

결과

let num = 9

switch num {
case num where num <= 10:
   print(num)
default:
   print("others")
}
결과

9

switch에서 조건을 걸고자 한다면 'where'을 활용하도록 한다.
위의 코드는 보통 다음과 같이 작성 되는데

let num = 9

switch num {
case let n where n <= 10:
   print(n)
default:
   print("others")
}

 

결과

9

num이 let n이 되는 이유(value binding)는 이후 강의에서 설명한다.
패턴에 condition을 추가할 수 있음을 기억하자.

Interval Matching

범위를 조건으로 사용한다.

let num = -2

switch num {
    case ...0:
        print("under zero")
    case 0 ... 10:
        print("under 10")
    case 10...:
        print("over 10")
    default:
    break
}

 

결과

under zero

FallThrough

let attempts = 10

switch attempts {
case ..<10:
   print("warning")
case 10:
   print("warning")
   fallthrough
default:
   print("reset")
}

 

결과

warning
reset

fallthrough 바로 이후의 case를 성립한 걸로 간주하고 실행한다.

 

Guard Statement

Statement

guard condition else {
    statements
}
guard optionalBinding else {
    statements
}

guard문에서 else문은 생략 할 수 없다.
guard문 내부에선 반드시 guard문을 종료해야한다.

//id를 받아 bool을 반환하는 validate 함수
func validate(id: String?) -> Bool {
    guard let id = id else {
        return false
    }
    
    guard id.count >= 6 else { //id의 길이 확인
        return false
    }
    return true
}

validate(id: nil)
validate(id: "abc")
validate(id: "WhySoSerious")
결과

false
false
true

guard문의 조건은 아래와 같이 한 번에 여러개를 지정 할 수도 있다.

func validate(id: String?) -> Bool {
    guard let id = id, id.count >= 6 else {
        return false
    }
    return true
}
func validateUsingIf() {
    var id: String? = nil
    
    if let str = id {
        if str.count >= 6 {
            print(str)
    }
}

func validateUsingGuard() {
    var id: String? = nil
        
    guard let str = id else { return } //if와 다르게 else 안에선 str을 호출 할 수 없다.
    guard str.count >= 6 else { return }
        
    print(str)
    }
}

 

같은 동작을 수행하지만 코드의 중첩을 막아 가독성을 좋게 한다.


Value Binding Pattern

Statement

case let name:
case var name:

matching 시킬 대상을 상수나 변수로 binding해 case 내에서 활용하기 위해 사용한다.

let a = 1

switch a {
case let x:
    print(x)
}

 

결과

1
let pt = (1, 2)

switch pt {
case let(x, y):
    print(x, y)
}
    
switch pt {
case (let x, var y):
    y = 7
    print(x, y)
}

switch pt {
case (_, var y):
    y = 7
    print(y)
}

 

결과

1 2
1 7
7

튜플로 value binding 하는 경우 각각을 따로 binding 할 수 있다.

 

Expression Pattern

Statement

A ~= B
//구조체 선언
struct Size {
    var width = 0.0
    var height = 0.0
}

let s = Size(width: 10, height: 20)

switch s {
case 1..<9:
    print("1~9")
case 10..< 99:
    print("10~99")
default:
    break
}

 

결과

//error

switch문에서 Size 구조체를 matching 하지만 case와 비교하는 방법을 모른다.
따라서 비교하는 방법을 알려줘야 할 필요가 있다.

struct Size {
    var width = 0.0
    var height = 0.0
    
    static func ~=(left: Range<Int>, right: Size) -> Bool {
    return left.contains(Int(right.width)) //width의 범위를 비교하여 성립하면 true를 반환한다.
    }
}

let s = Size(width: 3, height: 20)

switch s {
case 1..<9:
    print("1~9")
case 10..< 99:
    print("10~99")
default:
    break
}

 

결과

10~99

파라미터의 자료형과 순서가 중요하다.
첫번째 parameter는 case 다음에 오는 pattern의 자료형을 쓴다.
두번째 parameter는 switch 다음에 오는 pattern의 자료형을 쓴다.


Log

2021.08.06.
블로그 이전으로 인한 글 옮김 및 수정