4-4.switch 문

4-4-가.다중 선택

다중 선택문이란 하나의 변수값을 평가하여 각 값에 대해 개별적인 처리를 지정할 수 있는 문장이다. 예를 들어 사용자가 입력한 숫자가 1일 때는 이렇게 하고, 2일 때는 저렇게 하고, 3일 때는 요렇게 하고 각각의 값에 대한 처리를 다르게 지정하고자 할 때 다중 선택문을 사용한다. 키워드 switch를 사용하며 기본 형식은 다음과 같다.

 

switch (변수) {

case 1:명령1;break;

case 2:명령2;break;

....

case n:명령n;break;

default:명령;break.

}

 

switch문 다음의 괄호안에 평가할 변수를 적고 case문에 이 변수가 가질 수 있는 값과 이 값에 대한 처리 코드를 작성한다. case를 끝낼 때는 break문으로 switch 블록을 강제로 탈출해야 한다. case는 원하는만큼 얼마든지 작성할 수 있다. default는 case의 특별한 경우로 변수가 앞쪽 case에 있는 값 이외의 값을 가질 때의 처리를 지정한다.

기본 형식이 복잡해 보이지만 구체적인 예를 들어 보면 쉽게 이해가 갈 것이다. 다음 예제는 사용자로부터 입력받은 정수값이 얼마인가를 문장으로 출력한다.

 

: switch

#include <Turboc.h>

 

void main()

{

     int i;

 

     printf("값을 입력해 주세요 : ");

     scanf("%d",&i);

 

     switch (i) {

     case 0:

          printf("입력한 값은 0입니다.\n");

          break;

     case 1:

          printf("1을 입력했습니다.\n");

          break;

     case 2:

          printf("2입니다.\n");

          break;

     default:

          printf("0,1,2가 아닌 다른 수입니다.\n");

          break;

     }

}

 

i에 값을 입력받아 switch문으로 i값에 대해 다중 분기한다. case 0는 i가 0일 때의 동작을 지정하는데 "입력한 값은 0입니다."라는 메시지를 출력하였다. case1, case 2는 i가 1이거나 2일 때의 동작을 지정하는데 각각 다른 종류의 메시지를 출력했다. default는 위쪽 case에서 지정한 0, 1, 2중 어떤 것도 아닐 때의 동작을 지정한다. 순서도는 다음과 같다.

switch문은 변수값을 가능한 값과 모두 비교해 보고 그 중 변수값과 맞는 case를 선택하여 실행한다. 변수에 대한 일종의 조건 판단문이므로 if else if문으로도 똑같은 예제를 작성할 수 있다. 다음은 switch를 쓰지 않고 다시 작성해 본 것이다.

 

: switch2

#include <Turboc.h>

 

void main()

{

     int i;

 

     printf("값을 입력해 주세요 : ");

     scanf("%d",&i);

 

     if (i == 0) {

          printf("입력한 값은 0입니다.\n");

     } else if (i == 1) {

          printf("1을 입력했습니다.\n");

     } else if (i == 2) {

          printf("2입니다.\n");

     } else {

          printf("0,1,2가 아닌 다른 수입니다.\n");

     }

}

 

if문으로 i를 가능한 각각의 값과 비교해 보고 대응되는 메시지를 출력했다. 결과는 동일하지만 가능한 값의 종류가 아주 많다면 일일이 if문으로 비교하기가 아주 귀찮고 소스가 지저분해진다. switch문은 변수가 가질 수 있는 가능한 값을 case로 깔끔하게 선택하므로 소스를 읽기가 훨씬 더 편하고 case를 추가하는 것도 더 쉽다. 다음은 switch문의 일반적인 주의 사항이다.

 

switch문으로 평가할 수 있는 변수는 주로 정수형이다. int, unsigned, short같은 정수형 변수에 대해서만 switch문을 쓸 수 있으며 실수나 사용자 정의형 등은 다중 선택에 사용할 수 없다. 문자형, 열거형 등은 정수형과 호환되므로 switch문에 사용할 수 있다.

case 다음에는 반드시 정수 상수 하나가 와야 한다. 변수는 올 수 없으며 범위를 지정할 수도 없다. 만약 변수값끼리 비교하거나 일정한 범위에 있는지를 보려면 switch문 대신 if문을 사용해야 한다.

case문은 점프 위치를 지정하는 일종의 레이블이기 때문에 순서에 대한 제약은 없다. case 0, case 1, case 2 순으로 반드시 정렬할 필요는 없고 원하는 순서대로 작성해도 상관없다. default문도 반드시 switch의 끝에만 올 수 있는 것은 아니나 제일 마지막에 두는 것이 보기에 좋고 논리적으로 안정감이 있어 보인다.

default에 대한 처리가 필요치 않으면 생략할 수 있다. 만약 해당하는 case가 없고 default도 없으면 switch문 전체가 무시된다.

조건에 맞는 case를 만나면 case 아래에 있는 명령들을 순서대로 실행한다. 따라서 case 다음에 { } 괄호를 싸 줄 필요가 없다. 대신 case의 끝에는 break를 두어 switch문을 끝내도록 한다. 만약 break가 없으면 다음 case의 명령까지도 계속 실행한다. 이런 특성을 이용하면 두 가지 값에 대해 동일한 처리를 할 수 있다.

 

switch (ch) {

case 'a':

case 'A';

     // A에 대한 처리

     break;

}

 

이렇게 작성하면 ch가 대문자 A이거나 소문자 a이거나 동일한 처리를 하게 된다. case 'a'에 break가 없기 때문에 case 'A' 다음의 명령이 계속 실행되기 때문이다. switch문은 범위를 점검할 수 없지만 범위가 아주 좁다면 이런 식으로 break없이 case 몇 개를 나열해서 동일한 처리를 하도록 할 수는 있다. switch문의 이런 특성이 응용하기에 따라서는 다소 편리한 면도 있지만 실수로 break를 누락했을 때 컴파일러가 이를 에러로 보고하지 않으므로 원치않는 결과가 발생하는 경우도 종종 있다.

그래서 switch문을 쓸 때는 항상 break를 제대로 붙였는지 주의해야 하며 마지막 끝 부분의 case에는 break가 필요없다 하더라도 일단은 붙여 놓는 것이 안전하다. switch문의 break 효과는 직관적이지 못하고 실수할 가능성이 높아서 다른 언어 사용자가 C를 공격하는 핸디캡이 되기도 한다. 최신 언어인 C#은 break가 없는 case를 명백한 에러로 보고하여 이런 위험을 제거했다.