본문 바로가기

Programming Language/basic C Language

4. 제어문 - if, else if, else, switch~case

4. 제어문 - if, else if, else, switch~case

 

1. Intro

이전 단원을 통해 많은 정보를 반복 작업을 통해 간단하게 처리하는 방법에 대해 알아보았다. 하지만 우리는 그러한 단순 일괄 계산보다 더 많은 것을 원할 때가 있다. 예를 들어 1부터 10까지의 정수를 출력하는 데, 2의 배수는 2배를, 3의 배수는 3배를 해서 출력한다고 하자. 단순 반복문에 의한 일괄 계산으로는 하지 못할 것이다. 이러한 연산의 방향을 제어하는데 필요한 개념이 제어문이다.


1. if

영어 단어 if는 '만약에 ~라면'이라는 뜻을 가진다. 동일하게, 조건문 if는 실행 조건이 참일때 동작을 하도록 하는 조건문이다. 기본 형식은 아래와 같다. 

if (/*조건식*/) {
	실행할 동작;
}

예제를 통해 실제로 어떻게 사용되는지 보자.


예제 1. 정수를 하나 입력받아, 그것이 2의 배수이면 yes를 출력하시오.

#include <stdio.h>

int main()
{
	int a;
	scanf("%d", &a);
	if (a % 2 == 0) {
		printf("yes");
	}
	return 0;
}

너무나도 간단한 코드라 자세히 설명하지는 않겠다. 2의 배수이면 2로 나눈 나머지가 0이기 때문에 조건식에서 "a%2 == 0"으로 표현하였다.


# 2개 이상의 조건에 대하여

어떤 정보를 고를 때 2개 이상의 조건을 고려하는 경우는 굉장히 많다. 예를 들어, 마트에서 우유를 살 때, '서울우유'이면서 '유통기한이 3일 이상 남은' 우유를 고르거나, 2의 배수이면서 동시에 5의 배수인 수를 고르는 것이다. 또는, 여러 개의 조건 중 하나만 맞아도 고르는 경우도 있을 수 있다. '매일우유'나 '서울우유'이면서 '유통기한이 3일 이상 남은'우유를 고를 수 있고, 2의 배수이거나 3의 배수인 수를 고르는 것이다. 여기서 "그리고"와 "또는"의 개념에 해당하는 논리연산자 "&&", "||"가 등장한다.

우선 "&&"는 and의 의미로 양 옆의 조건이 모두 참이여야지만 참값을 반환한다. 다음 예제를 통해 살펴보자.


예제 1. 1부터 100까지의 수 중, 7의 배수이면서 동시에 13의 배수인 수를 모두 출력하시오.

#include <stdio.h>

int main()
{
	int i;
	for (i = 1; i <= 100; i++) {
		if (i % 7 == 0 && i % 13 == 0) {
			printf("%d ", i);
		}
	}
	return 0;
}

if 내의 조건문은 다음과 같다.

i % 7 == 0 && i % 13 == 0

이를 우리말로 "i를 7로 나눈 나머지가 0이고 i를 13으로 나눈 나머지가 0이다"와 같이 풀어쓸 수 있다.


"||"는 or의 의미로, 양 옆의 조건 중 하나만 참이어도 참을 반환한다. 다음 예제를 풀어보자.



예제 2. 1부터 100까지의 수 중, 7의 배수이거나 13의 배수인 수를 모두 출력하시오.

#include <stdio.h>

int main()
{
	int i;
	for (i = 1; i <= 100; i++) {
		if (i % 7 == 0 || i % 13 == 0) {
			printf("%d ", i);
		}
	}
	return 0;
}

if 내의 조건문은 다음과 같다.

i % 7 == 0 || i % 13 == 0

이를 우리말로 "i를 7로 나눈 나머지가 0이거나, i를 13으로 나눈 나머지가 0이다"와 같이 풀어쓸 수 있다.


2. else if

하나의 값에 대해 여러가지 조건을 붙일 수 있다. 예를 들어, 어떤 학생의 점수를 입력받아서, 90점 이상이면 A, 90점 미만 80점 이상이면 B, 80점 미만 70점 이상이면 C, 70점 미만이면 D를 출력하는 프로그램을 만든다고 가정하자. 그럼 다음과 같은 코드를 작성할 것이다.

#include <stdio.h>

int main()
{
	int score;
	scanf("%d", &score);
	if (score >= 90) {
		printf("A");
	}
	if (score >= 80) {
		printf("B");
	}
	if (score >= 70) {
		printf("C");
	}
	if (score < 70) {
		printf("D");
	}
	return 0;
}

하지만 위 코드를 실행하고 100을 입력하면 ABC가 출력이 될 것이다. 다시 말해 3개의 if문이 실행되었다는 것이다.

if는 조건문이 참이면 일단 실행한다. 그래서 입력값이 100이면 90이상인 경우, 80이상인 경우, 70이상인 경우에 대해 모두 동작한다. 이러한 문제를 해결하기 위해 존재하는 것이 else if이다. else if를 사용해 고친 코드는 다음과 같다.


#include <stdio.h>

int main()
{
	int score;
	scanf("%d", &score);
	if (score >= 90) {
		printf("A");
	}
	else if (score >= 80) {
		printf("B");
	}
	else if (score >= 70) {
		printf("C");
	}
	else if (score < 70) {
		printf("D");
	}
	return 0;
}

else if는 처음 if가 거짓인 경우에만 조건문이 참인지 거짓인지를 판단하는 조건문이다. 즉 처음 if가 참인 경우에는 뒤에 나오는 else if 구문들은 모두 무시된다. 둘의 차이를 아래 순서도를 참고해 확인하자.



그림1. if만 사용한 경우                      그림2. else if를 같이 사용한 경우



else if는 무조건 if 다음에 등장해야 함에 주의해야 한다. 다시 말해 if 구문이 있어야 else if 구문이 존재할 수 있다는 것이다.  


3. else

else는 앞서 나온 if나 else if의 조건 중 맞는 것이 하나도 없는 경우에 실행할 동작을 기술할 때 사용한다. else 역시 앞에 if가 있어야 존재할 수 있음에 주의해야 한다. else를 적절히 사용하면 불필요한 조건문을 없앨 수 있다. 위의 코드를 다시 살펴보자.

#include <stdio.h>

int main()
{
	int score;
	scanf("%d", &score);
	if (score >= 90) {
		printf("A");
	}
	else if (score >= 80) {
		printf("B");
	}
	else if (score >= 70) {
		printf("C");
	}
	else if (score < 70) {
		printf("D");
	}
	return 0;
}

마지막 else if는 불필요한 조건문이다. 70보다 크거나 같지 않은 모든 수에 대해서는 D를 출력할 것이기 때문이다. 이런 경우에 else를 사용한다. else를 사용하여 다시 쓰면 아래와 같아진다.

#include <stdio.h>

int main()
{
	int score;
	scanf("%d", &score);
	if (score >= 90) {
		printf("A");
	}
	else if (score >= 80) {
		printf("B");
	}
	else if (score >= 70) {
		printf("C");
	}
	else{
		printf("D");
	}
	return 0;
}

보다 직관적인 코드가 되었다. 이를 순서도로 나타내면 아래와 같다.



정보 처리의 조건을 붙이는 방법은 정말 다양하다. 가장 좋은 것은 분류 기준이 명확하며 직관적이고 간결한 조건 체계를 만드는 것이다.



4. switch~case


게임 첫 화면에 나오는 메뉴 버튼을 생각해보자. 내가 좋아하는 마리오를 생각해보면 1. 1인 플레이 2. 2인 플레이 3. 환경설정 처럼 스위치가 나뉘어 있다.

사진 출처 : 한국닌텐도(https://www.nintendo.co.kr/3DS/software/nsmb2/addcourse/purchase.html)


이런 버튼을 CUI창에서 구현한다고 가정해보자. 버튼을 직접 누를 수는 없으니 버튼 번호를 입력받으면 될 것이다. 그리고 입력 받은 번호에 따라 적절한 동작을 수행하도록 조건문을 사용하면 될 것이다. 그런데 여기서 if와 else if를 사용하면 물론 동작을 하겠지만 직관적이지는 않을 것이다.

#include <stdio.h>

int main()
{
	int button;
	scanf("%d", &button);
	if (button == 1) {
		/* 1번 동작 */
	}
	else if (button == 2) {
		/* 2번 동작 */
	}
	else if (button == 3) {
		/* 3번 동작 */
	}
	else if (button == 4) {
		/* 4번 동작 */
	}
	else {
		printf("올바른 버튼을 입력하세요");
	}
	return 0;
}

이를 보다 직관적이고 간결하게 표현하기 위해 존재하는 것이 switch~case 조건문이다. 우선 switch-case 조건문의 기본 형식은 아래와 같다.


switch([버튼 변수])
{
     case [변수가 가질 수 있는 첫 번째 값]:             // case 1: 처럼 맨 끝에 콜론 ":"이 붙음에 주의하라
           [첫 번째 값에 대한 동작];
           break;
     case [변수가 가질 수 있는 두 번째 값]:
           [두 번째 값에 대한 동작];
           break;
     ...
     case [변수가 가질 수 있는 마지막 값]:
          [마지막 값에 대한 동작];
          break;

     default:
          [그 외 값에 대한 동작];
          break;
}

switch([변수 이름])을 통해 값을 던져주고 case [값]: 으로 받는다고 생각하면 이해하기 쉬울 것이다. 주의해야 할 점은 각 case의 동작을 서술한 후 끝에 반드시 break;를 붙여야 한다는 것이다. break;를 쓰지 않으면 다음 case의 동작까지 실행해버리기 때문이다.

default는 switch로 던져진 수를 받을 case가 없을 때 실행하는 동작을 담당한다. 반드시 존재할 필요는 없다.


switch~case 조건문을 사용해 작성한 버튼 코드는 아래와 같다.

#include <stdio.h>

int main()
{
	int button;
	scanf("%d", &button);
	switch (button) {
		case 1:
			/* 1번 동작 */
			break;
		case 2:
			/* 2번 동작 */
			break;
		case 3:
			/* 3번 동작 */
			break;
		case 4:
			/* 4번 동작 */
			break;
		default:
			printf("올바른 버튼을 입력하세요");
			break;
	}
	return 0;
}

위의 코드보다 확실히 버튼의 느낌이 나는 것 같다.

예전에는 처리 속도때문에 switch-case 대신 if를 사용하라고 했지만 요즘은 점점 switch~case를 받아들이고 어떠한 경우에 대해서는 가독성을 이유로 switch~case의 사용을 장려하는 분위기이다. 중요한 것은 목적에 맞는 코드를 작성하기 위해 if, else if, else 그리고 switch~case를 적절히 사용하는 것이다.

'Programming Language > basic C Language' 카테고리의 다른 글

8. 구조체  (0) 2018.10.06
5. 함수  (0) 2018.10.06
3. 배열, 반복문 (while, for, do~while)  (0) 2018.10.06
2. 변수와 자료형과 연산자  (0) 2018.10.06
1. 표준입출력  (0) 2018.10.06