제어문

이인혁·2024년 5월 1일

C

목록 보기
4/23

시작하기에 앞서 C/C++ 같은 C언어계열은 일방적 실행흐름을 가지고 있습니다. 이럴때 실행흐름을 제어하기 위해 사용하는 것을 제어문이라고 합니다.

1. 제어문의 종류

제어문의 종류에는 조건문 분기문 반복문 등이있습니다.

조건문은 말 그대로 어떠한 조건에 참(TRUE)인지 거짓(FALSE)인지에 따라 결과가 달라져 나오는 명령문입니다. 조건문의 종류로는 if if~else if~else if switch등이 있습니다.

분기문은 조건문과 반복문에 중간에서 주어진 조건의 흐름을 바꿀 수 있는 구문입니다. 쉽게 말하면 조건문에 따라 반복문 건너뛰기반복문 종료등이 가능합니다. 분기문의 종류로는 contine break 그리고 무조건 분기인goto문등이 있습니다.

반복문은 주어진 조건이 충족이 될 때까지 반복적으로 문장을 수행시키는 명령문입니다. 프로그램을 처리하는 부분에 있어서 반복적인 형태가 많습니다. 그렇기 때문에 가장 많이 사용되는 제어문이라고도 할 수 있습니다. 반복문의 종류로는 for while do-while등이 있습니다.

2. 반복문

if문(단일조건문)

if문은 조건식 결과에 따라서 명령문 실행 여부가 결정되는데, 조건식에는 참(True) 또는 거짓(False)의 값을 산출할 수 있는 연산식이나 불린(boolean)자료형이 올 수 있습니다.

예)
if(조건식) {
명령어들;
}

예시

int main() {
    int a = 20;
    int b = 30;
    if (a > b) { //단일 조건문
        printf("a : %d가 b : %d보다 크다.\n", a, b);
    }
    if (!(a - 20)) {
        printf("a가 20과 같다.\n");
    }
    if (a < 50 && a>10) {
        printf("a는 10과 50 사이에 있다.\n");
    }
    return 0;
}

결과

a가 20과 같다.
a는 10과 50 사이에 있다.

참고 C언어는 정수값을 가지고 논리값을 처리하기 때문에 조건식 부분에 정수식도 가능합니다. (0은 False 0이외의 숫자는 True)

if-else문(이중조건문)

if문의 조건식이 참이면 if문의 명령문이 실행되고, 조건식이 거짓이면 명령문의 거짓인 else구문에서 실행되며 전체 if문을 벗어납니다.

예시

int main() { // 이중 조건문
    unsigned char ch = 'A';
    if (ch == 'A') {
        printf("ch의 값은 A문자 입니다.\n");
    }
    else {
        printf("ch의 값은 A문자가 아닙니다.\n");
    }
    if (ch == 'B')
        printf("ch의 값은 B문자 입니다.\n");
    else
        printf("ch의 값은 B문자가 아닙니다.\n");
    int a = 20;
    int b = 30;
    if (a < b) {
        printf("a : %d가 b : %d보다 작다.\n", a, b);
    }
    else {
        printf("a : %d가 b : %d보다 크거나 같다\n", a, b);
    }
    if (b - 30) { 
        if (b < 30) {
            printf("b가 30보다 작다.\n");
        }
        else {
            printf("b가 30보다 크다.\n");
        }
    }
    else {
        printf("b는 30이다.\n");
    }
    return 0;
}

결과

ch의 값은 A문자 입니다.
ch의 값은 B문자가 아닙니다.
a : 20가 b : 30보다 작다.
b는 30이다.

참고 if문에 붙어있는 명령어가 한 줄인 경우에는 {}(중괄호 블럭)을 생략할 수 있습니다.

if-else if(다중조건문)

if-else문의 경우는 두 개의 블록 중 하나를 선택해서 실행하는 구조였는데, 이번에 설명하는 if-else if문은 셋 이상의 블록 중 하나를 선택해서 실행하는 구조입니다.

if문을 여러 개 쓰면 모든 if문을 훑지만 else if문은 하나가 참이면 명령어를 실행하고 빠져나갑니다.

예시

int main() {
    int money = 0;
    printf("용돈 금액을 입력하세요: ");
    scanf_s("%d", &money);
    if (money > 100000) { //다중 조건문
        printf("영화\n");
    }
    else if (money <= 100000 && money > 80000) {
        printf("볼링장\n");
    }
    else if (money <= 80000 && money > 60000) {
        printf("중국집\n");
    }
    else if (money <= 60000 && money > 40000) {
        printf("당구장\n");
    }
    else if (money <= 40000 && money > 20000) {
        printf("카페\n");
    }
    else { //else문은 생략 가능합니다.
        printf("낮잠\n");
    }
    return 0;
}

결과

용돈 금액을 입력하세요: 50000
당구장

switch-case문(선택문)

switch문은 if문과 마찬가지로 조건 제어문 입니다. 위에 내용인 if else if문과 유사하지만 switch문은 변수의 값에 따라 코드를 실행할 수 있게 제어할 수 있습니다.

switch문은 변수의 값에 따라서 실행문이 결정됩니다. 따라서 조건식이 많아질수록 더 복잡해지는 if문보다 코드가 간결하고 가독성이 좋은 장점이 있습니다.

다음은 리모컨을 switch문으로 조금이나마 재현해본 것입니다.

예시

int main() {
    int buttonNum = 0;  //버튼 번호 입력
    int loop = 1;
    while (loop) {
        printf("컨트롤 번호를 입력하세요: ");
        scanf_s("%d", &buttonNum);
        switch (buttonNum) {
        case 0:
            printf("TV ON\n");
                break;
        case 1:
            printf("TV OFF\n");
            break;
        case 2:
            printf("VOLUME UP\n");
            break;
        case 3:
            printf("VOLUME DOWN\n");
            break;
        case 4:
            printf("CHANNEL UP\n");
            break;
        case 5:
            printf("CHANNEL DOWN\n");
            break;
        case 100: //리모컨 종료
            loop = 0;
            break;
        default:
            printf("WRONG NUMBER\n");
            break;
        }
    }
    return 0;
}

결과

컨트롤 번호를 입력하세요: 0
TV ON
컨트롤 번호를 입력하세요: 1
TV OFF
컨트롤 번호를 입력하세요: 2
VOLUME UP
컨트롤 번호를 입력하세요: 3
VOLUME DOWN
컨트롤 번호를 입력하세요: 4
CHANNEL UP
컨트롤 번호를 입력하세요: 5
CHANNEL DOWN
컨트롤 번호를 입력하세요: 6
WRONG NUMBER
컨트롤 번호를 입력하세요: 100

switch문으로 간단하게 만들 수 있는 대표적인 것중에는 계산기도 있습니다. 복잡한 연산은 안되지만 간단한 연산은 가능합니다.

예시

int main() {
    char oper = 0;
    printf("연산 방법을 입력하세요(+,-,x,/):");
    scanf_s("%c", &oper);
    switch (oper) {
    case'+':
        //int a = 20;
        //case문 안에서 변수를 만들어 사용할 때 {}(중괄호 블럭)을 쓴 후에 변수를 정의해야 합니다.
    {
        int a = 20;
        int b = 20;
        printf("%d + %d = %d\n", a, b, a + b);
    }
    break;
    case'-':
    {
        int a = 20;
        int b = 30;
        printf("%d - %d = %d\n", a, b, a - b);
    }
    break;
    case'x':
    case'X':
    {
        int a = 20;
        int b = 30;
        printf("%d x %d = %d\n", a, b, a * b);
    }
    break;
    case'/':
    {
        int a = 20;
        int b = 30;
        printf("%d / %d = %f\n", a, b, a / (float)b);
    }
    break;
    default:
        printf("연산기호를 잘못 입력하셨습니다.");
        break;
    }
    return 0;
}

결과

연산 방법을 입력하세요(+,-,x,/):+
20 + 20 = 40
연산 방법을 입력하세요(+,-,x,/):-
20 - 30 = -10
연산 방법을 입력하세요(+,-,x,/):x
20 x 30 = 600
연산 방법을 입력하세요(+,-,x,/):/
20 / 30 = 0.666667
연산 방법을 입력하세요(+,-,x,/):=
연산기호를 잘못 입력하셨습니다.

3. 분기문

goto문(무조건분기문)

goto문에는 상향식 분기와 하향식 분기가 있습니다.

goto문으로 앞으로 보내면 상향식 분기라고 하고, 뒤로 보내면 하향식 분기라고합니다.

로직에 상관없이 강제로 이동시키기 때문에 나중에 코드의 가독성이 떨어집니다. 때문에 잘 사용하지는 않습니다.

예시

int main() {
    int inputValue = 0;
Start: //레이블 프로그램 코드 위치
    printf("정수값을 입력하세요(extit:-1): ");
    scanf_s("%d" , &inputValue);
    if (inputValue != -1) {
        printf("입력된 값은 %d입니다. 다시 시작합니다.\n", inputValue);
        goto Start; //무조건 분기문(goto)
    }
    printf("입력된 값은 %d입니다. 프로그램을 종료합니다.\n", inputValue);
    goto Exit;
    printf("절대 출력 안됨");
Exit: //레이블 프로그램 코드 위치
    printf("프로그래밍 종료\n");
    return 0;
}

결과

정수값을 입력하세요(extit:-1): 2
입력된 값은 2입니다. 다시 시작합니다.
정수값을 입력하세요(extit:-1): 1
입력된 값은 1입니다. 다시 시작합니다.
정수값을 입력하세요(extit:-1): 0
입력된 값은 0입니다. 다시 시작합니다.
정수값을 입력하세요(extit:-1): -1
입력된 값은 -1입니다. 프로그램을 종료합니다.
프로그래밍 종료

break문, continue문

break문은 for문, while문 등 반복문을 중지할 때 사용합니다.

continue문은 반복문에만 사용되는데, 해당 반복을 건너뛰는 역할을 합니다.

밑에 반복문에서 사용할 때 설명하므로 따로 예시는 올리지 않겠습니다.

4. 반복문

for문

for문은 반복문의 대표라고 할 수 있을만큼 가장 많이 사용되는 반복문입니다

for문에서 초기화식이 가장 먼저 실행되고, 조건식이 참이면 실행문을 한 번 실행합니다. 그리고 증감식으로 변수를 초기화 한 후에 다시 조건식으로 가서 참이 나오면 실행문을 실행하는 구조입니다. 반복하다가 조건문이 거짓이 되면 for문은 종료하게 되는 구조입니다.
예)
for(초기화식; 조건식; 증감식){
명령어들;
}

예시

int main() {
    printf("\n단일 for문\n"); //일차원적인 데이터를 다룰 때 사용
    for (int i = 0; i < 10; i++) {
        printf("i = %d\n", i);
    }
    printf("\n이중 for문\n"); //이차원적인 데이터를 컨트롤 할 때 사용
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            printf("i = %d, j = %d\n", i, j);
        }
    }
    printf("\n삼중 for문\n");
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            for (int k = 0; k < 10; k++) {
                printf("i = %d, j = %d, k = %d\n", i, j, k);
            }
        }
    }
    for (float a = 0.0f; a < 100.0f; a += 1.2f) {
        printf("a = %f\n", a);
    }
    for (int i = 0, j = 10; i < 10 && j>0; i += 2, j -= 2) {
        printf("i = %d, j = %d\n", i, j);
    }
    return 0;
}

결과

단일 for문
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
이중 for문
i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 0, j = 3
i = 0, j = 4
i = 0, j = 5
*
*
*
i = 9, j = 9
삼중 for문
i = 0, j = 0, k = 0
i = 0, j = 0, k = 1
i = 0, j = 0, k = 2
i = 0, j = 0, k = 3
i = 0, j = 0, k = 4
i = 0, j = 0, k = 5
i = 0, j = 0, k = 6
i = 0, j = 0, k = 7
i = 0, j = 0, k = 8
i = 0, j = 0, k = 9
i = 0, j = 1, k = 0
i = 0, j = 1, k = 1
i = 0, j = 1, k = 2
i = 0, j = 1, k = 3
i = 0, j = 1, k = 4
i = 0, j = 1, k = 5
i = 0, j = 1, k = 6
i = 0, j = 1, k = 7
*
*
*
i = 9, j = 9, k = 9
a = 0.000000
a = 1.200000
a = 2.400000
*
*
*
a = 99.599937
i = 0, j = 10
i = 2, j = 8
i = 4, j = 6
i = 6, j = 4
i = 8, j = 2

참고 for문은 초기식 조건식 증감식이 생략가능합니다.
for문은 무한히 중첩가능합니다.

while, do-while문

for문이 반복되는 횟수가 정해져 있다면, while문은 for문과 다르게 조건식이 참일 경우에 계속해서 반복하는 반복문입니다. 조건식이 거짓이 나온다면 반복 실행을 멈추고 while문을 종료합니다.

while문은 조건식에 의해 반복적인 실행을 합니다. do-while도 이점은 while문과 동일합니다. 하지만 while문은 조건식이 참이지 않으면 아예 실행이 안되지만 do-while문은 조건이 충족되지 않아도 무조건 한 번은 실행되는 점에 있어서 큰 차이점이 있습니다.

while문이든 do-while문이든 항상 탈출조건을 만들어놔야 합니다. 그래서 보통 while문에서 탈출하려고 if문과 함께 break문을 씁니다.

다음은 while과 do-while문의 사용 예입니다.

예시

int main() {
    int loopCount = 0;
    printf("while문\n");
    printf("정수값을 입력하세요: ");
    scanf_s("%d", &loopCount);
        while (loopCount > 10) {
        loopCount -= 10;
        printf("loopCount = %d\n", loopCount);
    }
    printf("do-while문\n");
    printf("정수값을 입력하세요: ");
    scanf_s("%d", &loopCount);
    do {
        loopCount -= 10;
        printf("loopCount = %d\n", loopCount);
    } while (loopCount > 0);
    return 0;
}

결과

while문
정수값을 입력하세요: 40
loopCount = 30
loopCount = 20
loopCount = 10
do-while문
정수값을 입력하세요: 60
loopCount = 50
loopCount = 40
loopCount = 30
loopCount = 20
loopCount = 10
loopCount = 0

while문을 탈출할 땐 goto문이 간결하기도 합니다. 잘쓰지 않는 goto문이지만 break문보다 간결할 때가 있습니다.

예시1

int main() {
    int i = 2000;
    int j = 3000;
    int k = 4000;
    int limitValue = 0;
    int exit = 0;
    printf("정수값을 입력하세요: ");
    scanf_s("%d", &limitValue);  
    //goto문을 사용
    while (i > 0) {
        i -= 10;
        while (j > 0) {
            j -= 10;
            while (k > 0) {
                k -= 10;
                printf("i = %d, j = %d, k = %d\n", i, j, k);
                unsigned int sum = i * j * k;
                if (sum < limitValue) {
                    printf("sum = %d, limitValue = %d\n", sum, limitValue);
                    goto LoopExit;
                    //중첩되어있는 반복문을 한 번에 탈출할 때 goto문을 사용하면 코드를 간결하게 처리 할 수 있습니다.
                }
            }
        }
    }
    LoopExit: //레이블
    return 0;
}

보시다시피 goto문을 사용했을 때 더 깔끔해보이는 코드도 있습니다. 그래서 유동적으로 판단해서 사용하는게 좋습니다.

profile
게임개발공부블로그

0개의 댓글