Coding/C

[C언어] goto 사용하기 - 코딩도장

GunP4ng 2023. 12. 18. 23:35

[코딩도장] Unit 32 ~ 33


1. goto 사용하기

1. goto 와 레이블 사용하기

goto 는 중간의 코드를 무시하고

원하는 부분으로 건너뛸 수 있는 제어문이다

goto 를 적절히 사용하면 코드를 좀 더 간결하게 할 수 있고

에러처리에 매우 유용하기 때문에 리눅스 커널에서도 자주 사용된다

 

if (num1 == 1)         // num1이 1이면
    goto ONE;          // 레이블 ONE으로 즉시 이동
else if (num1 == 2)    // num1이 2이면
    goto TWO;          // 레이블 TWO로 즉시 이동
else                   // 1도 아니고 2도 아니면
    goto EXIT;         // 레이블 EXIT로 즉시 이동

goto에 레이블을 지정하면 중간의 코드는 건너뛰고 바로 레이블로 이동한다

1을 입력하면 레이블 ONE 으로 이동하고

2를 입력하면 레이블 TWO 로 바로 이동한다

 

ONE:    // 레이블 ONE
    printf("1입니다.\n");
    goto EXIT;    // 레이블 EXIT로 즉시 이동

TWO:    // 레이블 TWO
    printf("2입니다.\n");
    goto EXIT;    // 레이블 EXIT로 즉시 이동

EXIT:    // 레이블 EXIT
    return 0;

위와 같이 레이블을 지정한뒤 실행할 코드를 작성한다

레이블 ONE 으로 이동했다면 아래에 있는 TWO , EXIT 까지 실행되기 때문에

EXIT 으로 바로 이동해 다음 코드가 실행되는 것을 막는다

 

예시와 같은 코드를 스파게티 코드라고 한다

코드가 간결해서 읽기 쉽지만 코드의 양이 많아지면 읽기가 너무 어려워진다

 

위의 코드를 if else 로 표현하면

if (num1 == 1)         // num1이 1이면
    printf("1입니다.\n");
else if (num1 == 2)    // num1이 2이면
    printf("2입니다.\n");

코드가 매우 간결해진다

이런 경우에는 goto를 사용하지 않는 것이 좋다

 

 

goto는 중첩 루프문을 빠져나오는데 효과적이다

break 을 사용하면 현재 루프만 빠져나오기 때문에 추가적인 코드가 더 필요하다

하지만 goto 를 이용하면 간단하게 빠져나올 수 있다

 for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            if (num1 == 20)    // num1이 20이라면
                goto EXIT;     // 레이블 EXIT로 즉시 이동

            num1++;
        }
    }

EXIT:    // 레이블 EXIT
    printf("%d\n", num1);    // 20

 

goto 를 이용하면 중첩 루프문 마다 break 을 사용할 필요가 없어진다

예시는 for 문이지만 while, do while 문도 goto 로 빠져나올 수 있다

 

 

goto 는 에러상황에 실행해야 하는 중복코드를 하나로 모을 수 있다

if (gender == 2)                 // 여자라면
{
    printf("안녕히계세요.\n");    // 중복 코드
    printf("문을 닫는다.\n");     // 중복 코드
    return 0;                    // 프로그램 종료
}

if (age < 30)                    // 30세 미만이라면
{
    printf("안녕히계세요.\n");    // 중복 코드
    printf("문을 닫는다.\n");     // 중복 코드
    return 0;                    // 프로그램 종료
}

if (isOwner == 0)                // 전월세라면
{
    printf("안녕히계세요.\n");    // 중복 코드
    printf("문을 닫는다.\n");     // 중복 코드
    return 0;                    // 프로그램 종료
}

위의 코드는 에러마다 인사를 하고 문을 닫는코드가 중복된다

 

 goto를 이용하면

if (gender == 2)
    goto EXIT;    // 에러가 발생했으므로 EXIT로 이동

if (age < 30)
    goto EXIT;    // 에러가 발생했으므로 EXIT로 이동

if (isOwner == 0)
    goto EXIT;    // 에러가 발생했으므로 EXIT로 이동
 
EXIT:
    printf("안녕히계세요.\n");    // 에러 처리 코드를
    printf("문을 닫는다.\n");     // 한 번만 사용함

조건이 맞지 않아 에러가 발생할 때마다 goto 로 EXIT 으로 이동해 코드를 실행하게 된다

 

 

2. FizzBuzz

1. FizzBuzz

FizzBuzz 는 간단한 프로그래밍 문제이다

  • 1에서 100까지 출력
  • 3의 배수는 Fizz 출력
  • 5의 배수는 Buzz 출력
  • 3과 5의 공배수는 FizzBuzz 출력
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
    for (int i = 1; i <= 100; i++) {
        if (i % 3 == 0 && i % 5 == 0) {
            printf("FizzBuzz\n");
            continue;
        }
        if (i % 3 == 0) {
            printf("Fizz\n");
            continue;
        }
        if (i % 5 == 0) {
            printf("Buzz\n");
            continue;
        }
        printf("%d\n", i);
    }
    return 0;
}

FizzBuzz 문제를 풀 때 주의할 점은

3과 5의 공배수를 FizzBuzz 로 구현하는 것이다

 

조건의 순서대로 if 문을 이용해서 구현하면

3의 배수는 Fizz

5의 배수는 Buzz

3과 5의 공배수는 FizzBuzz

 

하지만 3과 5의 공배수가 나오면

3의 배수인지 먼저 확인하기 때문에 

Fizz가 출력되게 된다

 

따라서 3과 5의 공배수를 FizzBuzz 로 출력하기 위해서는

3과 5의 공배수를 출력하는 조건을

제일 위에 작성해야 한다

 

 

코드를 매우 단축해서도 작성할 수 있다

int main()
{
    for (int i = 0; ++i <= 100;)    // 조건식 안에서 변화식을 함께 작성
        printf(i % 3 ? i % 5 ? "%d\n" : "Buzz\n" : i % 5 ? "Fizz\n" : "FizzBuzz\n", i);
        // 삼항 연산자를 세 번 사용하여 printf 안에서 처리

    return 0;
}

3. 심사문제

32.6 중첩 루프 빠져나오기

다음 소스 코드를 완성하여 200과 300이 각 줄에 출력되게 만드세요.

정답에는 밑줄 친 부분에 들어갈 코드만 작성해야 합니다.

#include <stdio.h>

int main()
{
    int num1 = 0;

    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            if (num1 == 10)
                goto _____

            num1++;
        }
    }

EXIT1:
    printf("100\n");

EXIT2:
    printf("200\n");

EXIT3:
    printf("300\n");

    return 0;
}

 

정답

EXIT2;

 

EXIT2 로 이동하면 아래의 EXIT3 까지 출력하기 때문에

200과 300이 출력되게 된다


33.8 5와 11의 배수, 공배수 처리하기

표준 입력으로 정수 두 개가 입력됩니다(첫 번째 입력 값의 범위는 1~1000, 두 번째 입력 값의 범위는 10~1000이며 첫 번째 입력 값은 두 번째 입력 값보다 항상 작습니다). 첫 번째 정수부터 두 번째 정수까지 숫자를 출력하면서 5의 배수일 때는 "Fizz", 11의 배수일 때는 "Buzz", 5와 11의 공배수일 때는 "FizzBuzz"를 출력하는 프로그램을 만드세요(scanf 함수 호출 전에 문자열을 출력하면 안 됩니다).

정답에는 C 언어 컴파일러에서 정상적으로 컴파일되는 전체 코드를 입력해야 합니다.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main() {
    int num1, num2;
    scanf("%d %d", &num1, &num2);

    for (int i = num1; i <= num2; i++) {
        if (i % 5 == 0 && i % 11 == 0) {
            printf("FizzBuzz\n");
            continue;
        }
        if (i % 5 == 0) {
            printf("Fizz\n");
            continue;
        }
        if (i % 11 == 0) {
            printf("Buzz\n");
            continue;
        }
        printf("%d\n", i);
    }
    return 0;
}