language/c

[C언어] 04. 조건문

렁치 2026. 7. 27. 12:00

지금까지의 프로그램은 위에서 아래로 한 줄씩 차례대로 실행됐다. 하지만 실제 프로그램은 "조건에 따라 다르게" 동작해야 한다. 이렇게 실행 흐름을 바꾸는 문장을 제어문이라 하고, 그중 조건에 따라 갈래를 나누는 것이 조건문이다.


0. 제어 구조의 세 가지 형태

 

구조 설명
순차 구조 위에서 아래로 차례대로 실행
선택 구조 조건에 따라 실행할 문장을 선택 (조건문)
반복 구조 조건이 참인 동안 문장을 반복 (반복문)

 

모든 프로그램은 이 세 구조의 조합으로 만들어진다. 이 글에서 다루는 건 가운데의 선택 구조다.


1. if 문

if는 조건식이 참일 때만 중괄호 안의 문장을 실행한다.

if (조건식) {
    조건이 참일 때 수행할 문장;
}

 

int iNo = 10;
if (iNo > 0) {
    printf("양수입니다.\n");   // iNo가 0보다 클 때만 실행
}
printf("이 줄은 조건과 무관하게 항상 실행됩니다.\n");

 

문장이 하나여도 중괄호를 쓰자
실행할 문장이 한 줄이면 중괄호를 생략할 수 있지만, 생략하지 않는 편이 좋다. 나중에 문장을 추가할 때 중괄호가 없으면 if에 포함되지 않아 버그가 생기기 쉽기 때문이다.

실제로 중괄호 없이 줄을 추가했다가, 두 번째 줄이 조건과 무관하게 항상 실행되는 버그를 만난 적이 있다. 그 뒤로는 한 줄이어도 중괄호를 붙이게 됐다.


2. if ~ else 문

조건이 거짓일 때 실행할 내용을 else에 적는다. 두 갈래 중 하나는 반드시 실행된다.

if (조건식) {
    참일 때;
} else {
    거짓일 때;
}

 

elseif 없이 단독으로 쓸 수 없고, 한 if에 한 번만 붙는다.

 

int n;
scanf("%d", &n);
if (n % 2 == 0)
    printf("짝수\n");
else
    printf("홀수\n");

3. if ~ else if ~ else 문

여러 조건을 순서대로 검사할 때 쓴다. 위에서부터 검사해 처음 참이 되는 가지만 실행하고 나머지는 건너뛴다.

if (조건1) {
    ...
} else if (조건2) {
    ...
} else {            // 모든 조건이 거짓일 때 (한 번만)
    ...
}

 

성적으로 학점을 매기는 예처럼, 조건이 겹치지 않게 범위를 나눠 쓰는 것이 핵심이다.

if (score >= 90)      printf("A\n");
else if (score >= 80) printf("B\n");
else if (score >= 70) printf("C\n");
else                  printf("F\n");

 

순서가 중요하다. score >= 70을 맨 위에 두면 90점도 거기서 걸려 C가 되어버린다. 좁은(큰) 조건부터 차례로 내려오게 배치한다. 처음에 순서를 뒤집어 90점이 C로 나오는 걸 보고, "처음 참인 가지만 실행"의 의미를 제대로 이해했다.


4. switch 문

하나의 변수를 여러 특정 값과 비교할 때는 switchif-else if보다 깔끔하다. 단, 정수나 문자 같은 이산적인 값 비교에만 쓸 수 있다.

switch (변수) {
    case 값1:
        문장1;
        break;
    case 값2:
        문장2;
        break;
    default:
        그 외의 경우;
        break;
}

 

break를 빠뜨리면 다음 case로 흘러간다 (fall-through)
각 case 끝에 break가 없으면, 일치한 case부터 아래 case들이 break를 만날 때까지 줄줄이 실행된다. 의도한 동작이 아니라면 반드시 break를 넣어야 한다. 반대로 이 성질을 일부러 이용해 여러 case가 같은 코드를 공유하게 만들기도 한다.

 

int menu;
scanf("%d", &menu);
switch (menu) {
    case 1: printf("아메리카노 1500원\n"); break;
    case 2: printf("카페라떼 2000원\n");   break;
    case 3: printf("아이스티 2500원\n");   break;
    default: printf("없는 메뉴입니다\n");   break;
}

 

break를 빠뜨려 메뉴 하나만 골랐는데 아래 메뉴까지 줄줄이 출력된 적이 있다. fall-through를 글로만 봤을 땐 와닿지 않았는데, 직접 겪으니 왜 break가 필수인지 확실해졌다.


5. 수업 코드로 보는 윤년 판별

윤년 규칙을 조건문으로 옮기는 예제다. 말로 된 규칙은 다음과 같다.

  • 4의 배수이면 윤년 후보
  • 100의 배수이면 평년
  • 단, 400의 배수이면 다시 윤년

순서도로 보면 먼저 입력을 받고, 윤년 여부를 iLeapFlag에 저장한 뒤 출력만 분기한다.

int iYear;
int iMod4;
int iMod100;
int iMod400;
int iLeapFlag;

printf("연도를 입력하시오: ");
scanf("%d", &iYear);

iMod4 = iYear % 4;
iMod100 = iYear % 100;
iMod400 = iYear % 400;
iLeapFlag = 0;

if (iMod4 == 0 && iMod100 != 0)
{
    iLeapFlag = 1;
}
else if (iMod400 == 0)
{
    iLeapFlag = 1;
}

if (iLeapFlag == 1)
{
    printf("%d년은 윤년입니다.\n", iYear);
}
else
{
    printf("%d년은 윤년이 아닙니다.\n", iYear);
}

 

입력 4의 배수 100의 배수 400의 배수 결과
2024 O X X 윤년
1900 O O X 평년
2000 O O O 윤년
2026 X X X 평년

 

한 줄 논리식으로 바로 써도 되지만, 처음 배울 때는 iMod4, iMod100, iMod400, iLeapFlag처럼 중간 변수를 두면 어느 조건에서 결과가 갈렸는지 추적하기 쉽다.


오늘 느낀 점

  • 모든 프로그램이 순차·선택·반복 세 구조의 조합이라는 큰 그림을 먼저 잡으니, 조건문이 그중 한 조각이라는 위치가 분명해졌다.
  • 중괄호 생략 버그, 학점 순서 버그, switch의 fall-through까지 전부 직접 겪고서야 규칙의 이유가 납득됐다. 조건문은 눈으로보다 손으로 틀려봐야 배우는 게 많았다.
  • if(범위·복합)와 switch(딱 떨어지는 값)의 쓰임을 구분하니, 어떤 분기에 무엇을 쓸지 고민이 줄었다.

한 걸음 더

  • 윤년 판별처럼 조건이 복잡할 땐 논리 연산자로 한 식에 묶는다. "4의 배수이고 100의 배수는 아니거나, 400의 배수"는 (y%4==0 && y%100!=0) || (y%400==0)로 표현된다. 말로 된 규칙을 논리식으로 옮기는 연습이 조건문 실력을 키운다.
  • if-else ifswitch는 비슷하지만 쓰임이 다르다. switch는 "한 변수 == 특정 값"만 비교할 수 있어, "점수가 60 이상" 같은 범위 조건은 표현하지 못한다. 범위·복합 조건엔 if, 딱 떨어지는 값들의 분기엔 switch가 어울린다.
  • 문자도 사실 정수(아스키 코드)라서 switch (ch)if ('A' <= ch && ch <= 'Z') 같은 비교가 가능하다. 'A'가 65, 'a'가 97이라는 식으로 문자에 번호가 매겨져 있어, 대소문자·숫자 문자 판별을 범위 비교로 할 수 있는 것이다.

'language > c' 카테고리의 다른 글

[C언어] 03. 수식과 연산자  (0) 2026.07.20
[C언어] 02. 기본 변수와 입력  (0) 2026.07.10
[C언어] 01. 첫 프로젝트  (0) 2026.06.28