조건문
- 프로그램에서 하나 또는 그 이상의 조건값에 따라 특정 구문을 시행하도록 프로그램의 흐름을 분기하는 역할
if 문
1. if 구문
if <조건식> {
<실행할 구문>
}
- 조건문은 반드시 Bool 타입의 true or false을 판단할 수 있는 형태의 구문
- 조건문이 true일 때, 코드 블록 내부의 구문이 실행됨
var adult = 19
var age = 15
if age < adult {
print("당신은 미성년자입니다")
} // 당신은 미성년자입니다
2. if ~ else 구문
- 조건식이 true일 때는 A 구문을, true이 아닐 때는 B 구문을 실행
if <조건식> {
<A 구문>
} else {
<B 구문>
}
- else 구문은 조건식이 참이 아닌 모든 경우 실행
- if block과 else block 둘 중 하나는 반드시 실행
- 이율배반 : 두 코드 블록이 모두 실행되는 경우는 있을 수 없음
let adult = 19
var age = 20
if age < adult {
print("당신은 미성년자입니다.")
} else {
print("당신은 성년자입니다.")
} // 당신은 성년자입니다.
if 구문의 중첩
var adult = 19
var age = 21
var gender = "W"
if adult > age {
if gender = "W" {
print("여성 미성년자입니다")
} else {
print("남성 미성년자입니다")
}
} else {
if gender == "W" {
print("여성 성년자입니다")
} else {
print("남성 성년자입니다")
}
} // 여성 성년자입니다
- 3단계 이상의 중첩 구문은 사용하지 않는 것이 좋음
3. if ~ else if 구문
- 비교할 조건이 여러 개일 경우
- 단순히 true or false로만 판단하기 어려운 여러 개의 조건이 있을 때
- else if 구문은 else와 달리 여러 번 사용 가능
if <조건1> {
<조건1이 true일 때 실행될 구문>
} else if <조건2> {
<조건2이 true일 때 실행될 구문>
} else {
<앞의 조건들을 전부 만족하지 않았을 때 실행할 구문>
}
if gender == "W" {
print("여성 성년자입니다")
} else if {
print("남성 성년자입니다")
} else {
print("어느 쪽에도 속하지 않습니다")
}
cf. else if 구문을 if 구문으로 대체할 수 있나요?
- 컴파일러는 if ~ else if 구문을 하나의 조건식으로 인식하지만, if ~ if 구문은 서로 별개의 조건문으로 인식
- if ~ else if 구문에서는 차례대로 조건식을 비교하다가 일치하는 것이 발견되면 더이상 비교를 진행하지 않고 조건식을 종료
- if ~ if 구문에서는 이미 일치하는 조건식을 발견하여도 이후의 모든 조건식을 비교한 후 구문을 마침
guard 구문
- 전체 구문을 조기 종료(Early Exit)하기 위한 목적으로 사용
- 후속 코드들이 실행되기 전에 특정 조건을 만족하는지 확인하는 용도로 사용
guard <조건식 또는 표현식> else {
<조건식 또는 표현식의 결과가 false일 때 실행될 코드>
}
예) Divide By Zero
// 입력받은 값을 이용하여 100으로 나누는 함수
func divide(base: Int) {
// Divide by Zero 방지(0으로 나눌 경우 오류 발생)
guard base != 0 else {
print("연산할 수 없습니다")
return // 함수 종료
}
// base 값이 0이 아닐 경우 코드 실행
let result = 100 / base
print(result)
}
- guard 구문은 if 구문으로 대체할 수 있음
func divide(base: Int) {
// guard 구문의 조건식과 반대로 바뀜
if base == 0 {
print("연산을 처리할 수 있습니다")
return
}
let result = 100 / base
print(result)
}
- guard 구문은 실행 흐름을 종료하기 위한 목적으로 사용되는 구문이므로 코드를 중첩해서 사용하지 않아도 됨
- 전체 코드를 굉장히 깔끔하고 단순하게 만들어줌
- 조건을 체크하여 실행 흐름을 종료시킬 때는 가급적 guard 구문을 사용하는 것이 좋음
- 실행 흐름을 이어나가고 싶은 경우에만 if ~ else 구문을 사용하는 것이 좋음
#available
- OS version 별로 구문을 분리해야 할 때 사용
if #available(<플랫폼이름 버전>, <...>, <*>) {
<해당 버전에서 사용할 수 있는 API 구문>
} else {
<API를 사용할 수 없는 환경에 대한 처리>
}
// 플랫폼 이름과 버전 사이는 공백으로 구분, 입력 개수는 제한이 없음
// 마지막은 *로 마감
if #available(iOS 17, macOS 14, watchOS 6, *) {
// iOS 17용 API 구문 또는 macOS 14 구문, watchOS 6용 API 구문
} else {
// API를 사용하지 못했을 때에 대한 실패 처리
}
switch 구문
- 입력받은 값을 패턴으로 비교하고 그 결과를 바탕으로 실행 블록을 결정하는 조건문
- 나열된 패턴들을 순서대로 비교하다가 일치하는 첫 번째 패턴의 코드블록 실행
- 다양한 가능성이 있는 여러 개의 조건 비교에 효율적으로 대응하기에는 조금 부족한 if 구문의 대안
switch <비교 대상> {
case <비교 패턴1> :
<비교 패턴1이 일치했을 때 실행할 구문>
case <비교 패턴2>, <비교 패턴3> :
<비교 패턴2 또는 비교 패턴3이 일치했을 때 실행할 구문>
default :
<어느 비교 패턴과도 일치하지 않았을 때 실행할 구문>
}
- swift의 switch 구문은 일치하는 비교 패턴이 있을 경우 해당 블록의 실행 코드를 처리하고, 더이상의 비교 없이 전체 분기문 종료
- 오직 하나의 case 구문만 처리하고 나면 더이상 비교 진행 X → break 구문 생략
- C나 Java에서는 비교 패턴이 일치할 경우 우선 실행 구문을 처리한 다음, 나머지 case에 대한 비교를 계속 진행
- 추가로 일치하는 패턴이 있다면 이를 모두 실행하고, 마지막 case를 비교한 후에야 분기문 종료
let val = 2
switch val {
case 1 :
print("일치한 값은 1입니다")
case 2 :
print("일치한 값은 2입니다")
case 2 :
print("일치한 값 2가 더 있습니다")
default :
print("일치한 값이 없습니다")
} // 일치한 값은 2입니다
// ------------------------------
// 다른 언어에서의 실행 결과 (break 문이 없음)
// 일치한 값은 2입니다
// 일치한 값 2가 더 있습니다
// 일치한 값이 없습니다
암시적인 Fall Through
- 패턴이 일치하는 case 블록을 실행하는 대신, 그 다음 case 블록으로 실행 흐름을 전달하는 문법
- 명시해주지 않아도 된다는 점에서 암시적인 Fall Through라고 함
// C언어 계열
let sampleChar : Character = "a"
switch sampleChar {
case "a" :
case "A" :
print("글자는 A입니다")
default :
print("일치하는 글자가 없습니다")
} // 글자는 A입니다
- 암시적인 Fall Through 가 적용되면 실행 흐름이 전달된 비교 블록은 패턴 일치 여부에 상관없이 실행 블록 처리
- 4행의 case 문과 일치하지만 6행이 실행됨
* swift에선 암시적 Fall Through를 지원하지 않음 : 명시적으로 fallthrough 구문 사용
let sampleChar : Character = "a"
switch sampleChar {
case "a" :
fallthrough
// 해당 블록은 비교 패턴이 일치할 경우 인접한 case 블록으로 실행 흐름 전달
// 실행 흐름을 전달받은 case 블록은 비교 패터의 일치 여부와 상관없이 작성된 구문 실행 후
// switch 구문 종료
case "A" :
print("글자는 A입니다")
default :
print("일치하는 글자가 없습니다")
} // 글자는 A입니다
switch 구문의 특성
- switch 구문에서 사용된 비교 대상은 반드시 하나의 비교 패턴과 일치해야 함
- 비교 대상이 비교 패턴 중 어느 것과도 일치하지 않아 분기문 내의 어떤 블록도 실행되지 못하는 경우를 switch 구문이 fail 했다고 부름
- 모든 case 구문에서 일치된 패턴을 찾지 못했을 경우에 대비하여 switch 구문에는 반드시 default 구문을 추가해야 함
- 하나의 case 키워드 다음에 하나 이상의 비교 패턴을 연이어 작성할 수 있음
var value = 3
switch value {
case 0, 1 :
print("0 또는 1입니다")
case 2, 3 :
print("2 또는 3입니다")
default :
print("default 입니다")
} // 2 또는 3입니다
- 튜플 내부의 아이템이 비교 대상과 부분적으로 일치할 경우, case 비교 패턴 전체가 일치하는 것으로 간주
- 이 때, 일치하지 않는 나머지 부분을 상수나 변수화 하여 사용 가능
var value = (2, 3)
switch value {
case let (x, 3) :
print("튜플의 두번째 값이 3일 때 첫 번째 값은 \(x)입니다.")
case let (3, y) :
print("튜플의 첫번째 값이 3일 때 두 번째 값은 \(y)입니다.")
case let (x, y) :
print("튜플의 값은 각각 \(x), \(y)입니다.")
} // 튜플의 두번째 값이 3일 때 첫 번째 값은 2입니다.
- 위 예의 패턴 비교 구문 세 개는 모두 성립함
- (x, 3)은 (2, 3)과 부분적으로 일치함 → 일치하지 않는 첫 번째 아이템을 변수로 처리하면 구문의 비교 조건을 만족시킴
- 변수 x는 필요한 것에 사용 가능
- (3, y)은 (2, 3)과 부분적으로 일치함 → 일치하지 않는 두 번째 아이템을 변수로 처리하면 구문의 비교 조건을 만족시킴
- (x, y)은 (2, 3)과 패턴적으로 일치함 → 변수로 처리된 부분은 '어떤 값이든 들어올 수 있다'는 의미
- 범위 연산자를 사용하여 해당 범위에 속하는 값을 매칭할 수 있음 (Interval Matching)
var passtime = 1957
switch passtime {
case 0..<60 :
print("방금 작성된 글입니다")
case 60..<3600 :
print("조금 전 작성된 글입니다")
case 3600..<86400 :
print("얼마 전 작성된 글입니다")
default :
print("예전에 작성된 글입니다")
} // 조금 전 작성된 글입니다
var value = (2, 3)
switch value {
case (0..<2, 3) :
print("범위 A에 포함되었습니다")
case (2..<5, 0..<3) :
print("범위 B에 포함되었습니다")
case (2..<5, 3..<5) :
print("범위 C에 포함되었습니다")
default :
print("범위 D에 포함되었습니다")
} // 범위 C에 포함되었습니다
- where 구문을 추가하여 각 case 블록 별로 복잡한 패턴까지 확장하여 매칭할 수 있음
var point = (3, -3)
switch point {
case let (x, y) where x == y :
print("\(x)와 \(y)은 x==y 선 상에 있습니다")
case let (x, y) where x == -y :
print("\(x)와 \(y)은 x==-y 선 상에 있습니다")
case let (x, y) where x == -y :
print("\(x)와 \(y)은 일반 좌표상에 있습니다")
} // 3와 -3은 x==-y 선 상에 있습니다"
- point 변수는 switch 구문의 case 블록에서 각각 x, y로 할당
- 해당 임시 변수들은 다시 where 구문에서 조건 비교에 사용
[Day6] Collective Types (1) : Array (0) | 2024.04.14 |
---|---|
[Day5] 흐름 제어 구문(3) : Control Transfer Statements (0) | 2024.04.10 |
[Day3-2] 흐름 제어 구문(1) : Loop Statements (0) | 2024.04.08 |
[Day3-1] Operator (0) | 2024.04.08 |
[Day2] Types of Data (0) | 2024.04.07 |
댓글 영역