본문 바로가기

iOS

[iOS] 반복문, 조건문, 제어 전달문

반복문, 조건문, 제어 전달문


Index

1. 반복문

2. 조건문

3. 제어 전달문





프로그램의 흐름을 제어하기 위해서는 실행 흐름을 능동적으로 제어하기 위한 구문을 이용한다.

스위프트에서는 성격에 따라 다음 세가지 종류로 흐름 제어 구문을 분류할 수 있다.

  1. 반복문 (Loop Statements)
  2. 조건문 (Conditional Statements)
  3. 제어 전달문 (Control Transfer Statements)

1. 반복문


반복문은 타 프로그래밍 언어에서 이용하는 반복문과 동일하다.

주어진 조건에 의해 특정 코드를 반복적으로 실행할 수 있게 해주는 구문이다.

스위프트에서 제공하는 반복문은 반복 횟수가 정해져 있는지를 기준으로 두 가지 방식으로 나눌 수 있다.

  • For 반복문
  • While 반복문

For 반복문은 in 키워드와 함께 사용되어 정해진 횟수만큼 주어진 코드 블록을 반복해서 실행한다.

정해진 횟수만큼만 반복하는 For 반복문과는 달리, While 반복문은 주어진 조건이 false가 될 때 까지 게속하여 구문을 반복한다.

따라서 미리 반복 횟수를 정하지 않아도 된다는 장점이 있기 때문에 반복 횟수를 예측하기 어려운 경우의 반복문에서 주로 이용된다.

while 반복문은 while 구문과 repeat~while 구문으로 나누어진다.

while 반복 : 매번 루프를 시작할 때 마다 조건식을 평가하여 반복을 진행할 지 말지 결정한다.

repeat~while 반복 : 루프를 완료할 때 마다 조건을 평가하여 다음 루프 실행 여부를 결정한다.

일단은 주어진 코드 블록을 실행한 뒤 다시 한번 루프를 실행할지 말지를 조건식을 통해 평가한다. -> 타 언어의 do~while 문과 동일하다.

For 반복문은 횟수에 의한 반복

While 반복문은 조건에 의한 반복

반복문 내에서 흐름을 제어하고자 할 때에는 break 구문과 continue 구문이 사용된다.
이 구문들은 제어 전달문으로서, 적절한 시점에 사용되어 코드 블록의 실행 흐름을 옮겨주는 역할을 한다.


1.1. for in 구문

스위프트에서 일정 횟수만큼 특정 구문을 반복하고자 할 때에는 for~in 구문을 이용한다.

구문 형식

for [루프 상수] in [순회 대상] {
    code
}

기본적으로 본 구문을 실행하기 위해서는 루프 상수, 순회 대상, 실행할 코드를 필요로 한다.

이 중 가장 중요한것은 순회 대상 으로 주로 iteration 한 성격을 갖거나 순번을 가지는 집단 자료형 또는 범위를 가지는 데이터 등이 사용되며, 이 대상의 길이나 내부 아이템의 개수만큼 구문이 반복 수행된다.

순회 대상으로 이용될 수 있는 자료형은 아래와 같은 것들이 있다.

  • 배열 (Array)
  • 딕셔너리 (Dictionary)
  • 집합 (Set)
  • 범위 데이터
  • 문자열 (String)

문자열은 Character 타입의 데이터들이 모여 이루는 집단적 성격의 데이터들이기 때문에 순회 대상으로 사용할 수 있다.

우리가 이전에 배웠던 닫힌 연산자를 순회 대상으로 사용할수도 있다.

for row in 1...5 {
    print(row)
}

// 1, 2, 3, 4, 5

for col in 1..<5 {
    print(col)
}

// 1, 2, 3, 4

이번에는 for~in 구문을 이용하여 문자열의 문자를 순회하는 방법을 알아보자.

String 은 단일 객체로 사용되지만, 그 구조를 들여다보면 Character 타입의 개별 문자들이 모여 이루어진 객체다. 이들 개별문자들이 모여서 하나의 문자열을 구성하므로 이 역시 순회 대상으로 사용할 수 있다.

다만, String 타입은 순회 처리를 지원하지 않으므로 다음과 같이 characters 의 속성을 이용해야 한다.


var lang = 'swift'
for char in lang.chracters {
    print("\(char)")
}

1.2. while 구문

앞에서 살펴본 for~in 구문은 미리 정의된 실행 횟수만큼 반복하지만 while 구문은 단순히 주어진 조건식이 false가 될 때 까지 실행 구문을 게속 반복 수행한다.

즉, while 구문은 '조건을 만족하는 동안' 게속 실행된다.

while 구문을 사용해야 하는 경우는 아래와 같다.

  • 실행 횟수가 명확하지 않은 경우
  • 직접 실행해보기 전까지는 실행 횟수를 알 수 없을때
  • 실행 횟수를 기반으로 할 수 없는 조건일 때

while 구문의 사용형식은 아래와 같다.

while [조건식] {
    code
}

조건식의 결과값은 true 또는 false로 반환해야 하며 false 일 경우 반복문의 실행은 종료되고 코드 블럭을 빠져나간다.


1.3. repeat~while 구문

repeat ~ while 구문은 타 언어의 do ~ while 구문에 해당하는 구문이다.

repeat ~ while 구문의 사용형식은 아래와 같다.

repeat {
    code
}
while [조건식]

위 처럼 우선 repeat 블럭으로 들어가 코드를 실행한 이후 조건식 을 검사하여 반복 여부를 결정한다.

즉, 처음부터 조건식의 결과값이 false를 반환하여도 적어도 한 번은 코드 블럭을 실행을 보장하는 특성을 가진다.


var n = 1024
while n <= 1000 {
    n *= 2
}

앞서 학습한 while 구문을 repeat~while 구문으로 변경해본다.

var n = 1024

repeat {
     n *= 2
} while (n < 1000)

while 구문과 repeat~while 구문에 이용된 조건식은 동일하지만 두 코드의 결과값은 다르다.

while 문은 n의 최종값이 1024이며,
repeat~while 문의 n의 최종값은 2048이다.

이처럼 repeat~while 구문은 적어도 한번은 꼭 실행해야 할 필요가 있는 경우 사용한다.

2. 조건문


조건문은 대부분 타 언어와 비슷한 흐름을 가지므로 swift 에서만 이용되는 조건문을 정리하도록 한다.

2.1. guard 구문

swiftguard 문은 if 구문과 마찬가지로 주어진 표현식의 결과에 따라 구문의 실행 여부를 결정짓는 방식의 조건문이다.

if구문과의 차이점은 guard 구문에서는 else 블록이 필수이지만, 표현식의 결과가 참일 경우 실행되는 블록이 없다는 점이다.

말로는 잘 이해가 되지 않으니 직접 예제 코드를 살펴보도록 한다.

guard [조건식 또는 표현식] else {
    [조건식 또는 표현식의 결과가 false인 경우 실행될 코드]
}

guard 구문은 조건에 따른 분기가 아닌 특정 조건을 만족하는지 확인하는 용도로 사용한다.

다시 말해 특정 조건을 만족하지 않은 채로 후속 코드를 실행하면 에러가 발생할 경우에, 전체 구문을 조기 종료하기 위한 목적으로 사용되는 것이 guard 구문이다.

guard 구문은 보통 함수나 메소드에서 사용되는데, 이때에는 return 구문이 조기 종료 처리 역할을 한다.

아래 예제를 살펴본다.

func divide(base : Int) {
    let result = 100 / base
    print(result)
}

주어진 예제에서는 base 변수를 통해 입력받은 값을 정수값 100으로 나누고, 그 몫을 출력하는 함수이다.

이 함수에서 주의해야 하는 부분은 입력하는 값을 이용하여 100으로 나눈다는 것이다.

만일 base 값이 0일 경우, Divide By Zero 오류가 발생한다.

따라서 입력받은 값이 0이 아닐때에만 해당 함수 내 코드를 실행해야 하고, 그렇지 않을 경우 함수의 실행을 중지해야 한다.

이런 경우를 제어할 때 어울리는 것이 바로 guard 문이다.

이 구문이 적용된 함수를 살펴보자.


func divide(base: Int) {

    guard base != 0 else {
        print("Divide By Zero")
        return
        // 0으로 나눌경우 프로그램 종료
    }

    // Base 가 0이 아닌 경우
    let result = 100 / Base
    print(result)
}

함수의 실행을 종료할 때에는 return 구문을 이용한다.

return 구문이 실행되면 이후의 코드가 남아있더라도 더이상 진행하지 않은채로 함수가 종료된다.

위와 같이 if 구문을 guard로 대체할 수 있다.

2.2. available 구문

앱 개발시에는 기기의 OS 버전별 호환을 위한 구문을 나누어 작성해야 할 경우가 발생한다.

이를 보통 현업에서는 API가 버전을 탄다 라고 표현한다고 한다.

이처럼 OS 버전별로 구문을 분리해야 할 때 #available 구문을 사용한다.

#available 구문을 사용하는 형식은 알애ㅘ 같다.


if #available([플랫폼 버전], [...], [*]) {
    [해당 버전에서 사용할 수 있는 API 구문]
} else {
    [API를 사용할 수 없는 환경에 대한 예외 처리]
}

#available 구문을 사용할 때에는 호출 연산자 () 를 이용해 플랫폼 이름과 버전 등의 인자값을 입력할 수 있다.

인자값은 가변 인자로 정의되어 있기 때문에 입력 개수의 제한이 없으며 쉼표로만 구분을 하고 마지막은 * 로 마감하여 인자값 입력이 끝났음을 선언한다.



#2.3. switch 구문

앞에서 다룬 ifguard 구문은 조건의 비교 결과에 따라 실행 여부가 결정되는 방식이었다면, switch 구문은 같은 분기문에 속해있지만 처리 방식이 다르다.

switch 구문은 입력받은 값을 여러 패턴과 비교하여 그 결과를 이용해 실행할 코드블럭을 결정하는 조건문이다.

이 구문은 나열된 패턴들을 순서대로 비교하다가 일치하는 첫번째 패턴의 코드 블럭을 실행한다.

switch 문은 아래와 같이 사용한다.

switch [비교 대상] {
    case [비교 패턴1] :
        [비교 패턴 1 만족시 실행할 구문]
    case [비교 패턴 2], [비교 패턴 3]:
        [비교 패턴2, 비교 패턴 3 만족시 실행할 구문]
    default:
        [일치하는 패턴이 없을 경우 실행할 구문]
}

모든 switch 구문은 비교 대상과 case 키워드로 시작하는 다양한 패턴을 나열하는 방식으로 구성된다.

비교 대상과 비교 패턴이 일치할 경우 그에 해당하는 구문이 실행된 이후 나머지 case에 대한 비교 및 검사 진행 없이 switch 문을 종료하고, switch 문 이후에 나오는 코드 블럭을 진행한다.

만일, 일치하는 비교 패턴이 없을 경우 default 구문을 실행한다.

타 언어에서 사용되는 switch 구문을 살펴보면 스위프트의 switch 구문과 몇가지의 차이점이 존재한다.

switch 구문에는 패턴이 일치하는 case 블록을 실행하는 대신, 그다음 case 블록으로 실행 흐름을 전달하는 문법이 있으며 이를 Fall Through 라고 한다.

스위프트에서는 명시적 Fall Through 만 지원한다.

아래 예시 코드를 살펴보며 이해를 돕자.


let sampleChar: Character = "a"

switch sampleChar {

    case 'a':
        fallthrough
    case 'A':
        print("A")
    default:
        print("일치하는 글자가 없다.")
}

// output : A

fallthrough 구문이 사용된 case 블록은 비교 패턴이 일치한 경우 인접한 case 블록으로 실행 흐름을 전달한다.

fallthrough 에 의해 실행 흐름을 전달받은 case 블록은 비교 패턴의 일치 여부와 상관없이 작성된 구문을 실행한 후 switch 구문을 종료한다.

switch 구문의 특성

스위프트에서 switch 구문에 사용된 비교 대상은 반드시 하나의 비교 패턴과 일치해야 한다.
만일 비교 패턴 중 어느 것과도 일치하지 않아 어떠한 블록도 실행되지 못할 경우 switch 구문이 실패(fail)했다고 부르는데, 스위프트는 이같이 실패한 switch 구문을 완전한 비교 패턴을 구성하지 못한 것으로 간주한다.

이에 따라 모든 case 구문에서 일치된 패턴을 찾지 못할 경우를 대비하여 switch 구문에는 반드시 default 구문을 추가해야 하며, 만일 default 를 생략하면 완전치 못한 구문으로 간주하여 오류가 발생한다.

따라서 switch 구문을 이용할 때는 비교 패턴 중 어느 하나라도 반드시 일치해야 한다.



3. 제어 전달문


제어 전달문은 코드의 한 부분에서 다른 부분에서 제어 흐름을 전달하여 코드의 실행 흐름을 변경하는 구문이다.

주로 반복문, 조건문, 함수 등에서 사용되며 스위프트에서 사용되는 제어 전달문은 아래와 같다.

  • break
  • continue
  • fallthrough
  • return

이 구문들은 각각의 쓰임에 따라 코드의 흐름을 제어하고, 다른 부분으로 제어를 전달하거나 기능을 종료한다.

이 중 fallthrough는 앞에서 switch 구문의 흐름을 제어할때 사용한 방법으로 , 일치된 case 블록의 실행을 다음 case로 전달할 때 사용한다.

각각의 키워드에 대해 간단히 살펴보도록 한다.

3.1. break

break 구문은 switch 구문에서 실행의 흐름이나 반복 실행 중인 루프를 조건식의 결과게 상관없이 즉각적으로 종료하는데 사용된다.

3.2. continue

break 구문이 필요에 따라 실행 흐름을 강제로 종료하거나 반복을 중단하기 위해 사용되는 키워드라면, continue는 이 구문 아래에 있는 실행 구문들을 건너뛰고 다음 반복을 시작하는 역할을 의미한다.

즉, break 구문이 반복문을 완전히 종료시킨다면 continue 구문은 반복문의 조건을 다시 평가하고 그 결과에 따라 다음 반복을 실행하여 전체 반복을 계속 유지하는지의 여부가 결정적 차이라고 할 수 있다.

'iOS' 카테고리의 다른 글

[iOS] Web Browser Project  (0) 2020.04.12
[iOS] 배열, 집합, 튜플 자료형  (0) 2020.04.11
[iOS] 변수와 상수, 자료형, 연산자  (0) 2020.04.11
[iOS] Music Player  (0) 2020.04.09
[iOS] Target-Action Pattern  (0) 2020.04.07