관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

선택문 2 - if문 활용과 switch ~ case문 본문

프로그래밍 언어/C 언어

선택문 2 - if문 활용과 switch ~ case문

huenuri 2024. 7. 30. 05:52

이번 장에서는 중첩되는 if문과 switch문에 대해 학습하게 된다. 일상생활과 마찬가지로 프로그램에도 다양하고 복잡한 선택의 순간이 많다.

따라서 if문을 자유롭게 응용하는 능력이 반드시 필요하다. if문을 중첩해서 사용하는 방법과 주의할 점을 살펴본 후, 다중 선택이 필요한 상황에 알맞은 switch ~ case문도 학습할 예정이다.

 

 

시작하기 전에

문제를 해결하다 보면 선행조건이 필요한 경우가 있다. 선행조건이 꼭 필요할 때 if문을 중첩해서 사용한다. 학점에 따라 장학금의 지급액이 다른 경우에는 if보다는 switch ~ case문을 사용하는 것이 더 편리하다.


 

 

 

1. if문 중첩

어떤 조건을 검사하기 전에 선행조건이 있다면 if문 안에 if문을 넣어 사용한다.

 

 

중첩된 if문

#include <stdio.h>
int main() {
    int a = 20, b = 10;
    if (a > 10) {
        if (b >= 0) {
            b = 1;
    } 
    else {
        b = -1;
        }
    }
    printf("a : %d, b : %d\n", a, b);
    return 0;
}

 

if ~ else문은 실행문이 많고 형태가 복잡하더라도 전체를 한 문장으로 취급한다. if문은 조건식이 참일 때 실행할 문장이 if ~ else문 한 문장이므로 중괄호는 생략할 수 있다. 다만 실행문의 범위를 쉽게 구분할 수 있도록 가능한 한 중괄호를 사용하는 것이 좋다.

 

 

 

if문을 중첩해서 쓰는 이유

 

1. 선행조건이 있으면 불필요한 조건 검사를 하지 않는다.

논리곱(&&)연산은 두 조건을 모두 만족해야 하므로 a > 10의 조건이 거짓이면 두 if문의 조건식은 모두 거짓이 되어 b값은 바뀌지 않는다.
따라서 a > 10의 조건이 참일 때만 b의 값에 따라 둘 중 한 문장을 실행하게 된다.

결국 논리적으로 if문을 중첩해 사용한 것과 같다. if문을 중첩하면 a > 10의 조건을 먼저 확인하고 참인 경우만 다음 조건을 따지므로 선행조건이 거짓이면 불필요한 연산을 줄일 수 있다.


 

 

 

2. 선행조건이 없어도 실행 효율을 위해 의도적으로 중첩해 사용할 수 있다.

 

 

a가 1~6중 어떤 값인지 판단하는 경우 1부터 하나씩 차례로 검사하는 방법보다 중간값인 3과 먼저 비교해 두 범위로 나누고, 그 범위에서 다시 비교하는 방식이 훨씬 더 효율적이다. 이렇게 하면 평균 조건 검사 횟수를 줄일 수 있다.

이 방법을 분할 정복 기법이라고 하는데 비교 항목이 많은 경우 if문을 여러 번 중첩해서 쓰면 실행 시간을 줄이는데 도움이 된다.


 

 

 

2. else 결합 문제

문법적으로 if문은 조건에 따라 실행할 문장이 한 문장인 경우 줄괄호를 생략할 수 있다. 그러나 이 경우에도 중첩 if문에서 중괄호를 반드시 써야 하는 경우가 있다. if ~ else문이 참일 때 실행문으로 기본 if문이 쓰이면 반드시 중괄호가 필요하다.

 

중첩 if문에서 중괄호가 반드시 필요한 경우

#include <stdio.h>
int main() {
  int a = 10, b = 20;
  if (a < 0) {
     if (b > 0)
  {
     printf("ok");
        }
  } 
  else {
     printf("ok");
  }
  return 0;
}

 

 

 

매달린 else 문제

Dangling else Problem(댕글링 else 문제)라고도 한다. if문을 중첩해 사용하다 보면 한 번은 꼭 만나게 되는 문제이다.

if문을 중첩해 사용할 때 뒤따르는 else의 위치가 모호해지면서 생기는 문제이다. 중괄호의 여부에 따라 전혀 다른 프로그램이 되므로 반드시 중괄호를 써서 다른 구문으로 해석되지 않도록 주의해야 한다.


 

 

3. switch ~ case문

 

기본 규칙

  1. 조건식으로 정수식만 사용해야 한다.
  2. 기본적으로 case는 break를 포함한다.

 

정수식은 정수형 상수나 변수를 쓸 수 있고, 수식을 사용할 때는 결과값이 정수여야 한다. case에 사용하는 상수식 역시 정수만 가능하다.

 

switch ~ case문의 사용

#include <stdio.h>
int main() {
  int rank = 2, m = 0;
  switch (rank) {
    case 1:
        m = 300;
        break;
    case 2:
        m = 200;
        break;
    case 3:
        m = 100;
        break;
    default:
        m = 10;
        break;
    }
    printf("m : %d\n", m);
    return 0;
}

 

 

 

break 생략

break는 필요에 따라 생략할 수 있다. break를 사 용하면 적절한 시점에 블록을 탈출해 필요한 부분만 선택적으로 실행할 수 있다. 필요에 따라 전체나 일 부를 생략할 수 있다. break가 있고 없고는 큰 차이가 난다.

 

break가 없으면 바로 아래의 문장이 함께 실행된다.switch ~ case문을 if문으로 바꿀 수도 있다.

 

 

default의 위치

switch ~ case문은 조건에 따라 case의 상수를 모두 비교한 후 일치하는 상수가 없는 경우 마지막에 default로 간다. default는 switch의 블록 안 어디에 있어도 결과는 같다. 보통 모든 case문을 적은 다음 마지막에 예외 상황을 처리할 때 사용한다.


 

 

단원 마무리

 

 

 


 

연습문제

 

문제 1

옷의 사이즈를 if문을 활용해 작성하시오.

#include <stdio.h>
int main(void) {
  int age = 25, chest = 95;
  char size;
	if (age < 20) {
		if (chest < 85) {
			size = 'S';
		}
		else if (chest < 95) {
			size = 'M';
		}
		else
			size = 'L';
	}

	else {
		if (chest < 90) {
			size = 'S';
		}
		else if (chest < 100) {
			size = 'M';
		}
		else
			size = 'L';
	}
	printf("사이즈는 %c입니다.\n", size);
	return 0;
}

 

 

문제 2

키보드로 수식을 입력하면 계산 결과를 출력하는 프로그램을 작성하시오. 정수 사칙연산만 입력한다.

#include <stdio.h>
int main(void) {
	int num1, num2, res;
	char ch;
	printf("사칙연산 입력(정수) : ");
	scanf_s("%d%c%d", &num1, &ch, 1, &num2);
	switch (ch) {
	case '+':
		res = num1 + num2;
		break;
	case '-':
		res = num1 - num2;
		break;
	case '*':
		res = num1 * num2;
		break;
	case '/':
		res = num1 / num2;
		break;
	}
	printf("%d%c%d=%d", num1, ch, num2, res);
	return 0;
}

 

scanf_s에서 크기를 지정하지 않으면 쓰레기값이 출력되기도 하니 주의해야 한다(특히 char형의 경우).


 

 

 

 

학습을 마치고

오늘은 이렇게 선택문의 개념을 정리하며 연습문제를 풀어보았다. 계산기를 만드는 프로그램은 선택문에서 기본으로 등장하는 문제이다. 처음에는 많이 어려웠는데 지금은 잘 풀 수 있게 되었다.

이제 오늘과 내일만 지나면 휴일이다. 목요일이 제일 힘든 것 같다. 그래도 지금까지 잘 버텨왔듯 잘 해낼 수 있으리라 본다. 가장 힘든 고비는 지난 것 같다. 매일 스스로와 한 약속을 지키며 열심히 하는 것만 남아있다~