← C 강의 목록으로
⚙️
중급 (Intermediate)
if · else · switch · 삼항

1단원 — 조건문

조건문은 프로그램의 **흐름을 가지가 갈리게** 합니다. 이 단원에서는 `if`/`else if`/`else`, 삼항 연산자, `switch`까지 분기 도구 세트를 익힙니다.

ifswitch삼항
소요 시간
1~2시간
난이도
📊 초급
선수 조건
🎯 기초 4단원
결과물
분기 흐름을 깔끔히 표현한다

이 강의에서 배우는 것

  • 1`if`/`else if`/`else`로 다단계 분기를 작성한다.
  • 2삼항 연산자 `?:`를 짧은 조건 표현에 활용한다.
  • 3`switch`/`case`/`break`/`default`의 동작을 정확히 안다.
  • 4조건의 부울 결과(0/0 아님)를 이해한다.

왜 조건문이 필요한가? — "갈림길의 신호등"

지금까지의 프로그램은 위에서 아래로 한 번에 흘렀습니다. 하지만 현실 문제는 거의 항상 "어떤 경우엔 A, 다른 경우엔 B"의 모양입니다.

text
            ┌──────────┐
            │ score≥90 │── Yes ──► A
            └──────────┘
                  │ No
                  ▼
            ┌──────────┐
            │ score≥80 │── Yes ──► B
            └──────────┘
                  │ No
                  ▼
                  C 이하

조건문은 이 갈림길의 **신호등**입니다.

핵심 개념

1) `if` / `else if` / `else`

c
if (score >= 90)      printf("A\n");
else if (score >= 80) printf("B\n");
else if (score >= 70) printf("C\n");
else                  printf("D 이하\n");
  • 위에서 아래로 검사하다가 **처음 참인 가지**만 실행합니다.
  • 그래서 `score >= 80`은 **"80 이상이면서 90 미만"** 의 의미가 자동으로 됩니다.

2) 삼항 연산자 `?:`

c
int max = (a > b) ? a : b;

`if-else` 한 줄짜리 단순 분기에 적합합니다. 너무 길어지면 일반 `if`로.

3) `switch` / `case`

c
switch (op) {
    case '+': result = a + b; break;
    case '-': result = a - b; break;
    default:  printf("알 수 없는 연산자\n");
}

흐름:

text
       ┌─────► case '+': ─► break  ─► (스위치 종료)
op? ───┼─────► case '-': ─► break  ─► (스위치 종료)
       └─────► default                 ─► (스위치 종료)

`break`가 없으면 다음 `case`로 **흘러내림**(fall-through)합니다. 의도한 게 아니면 잊지 말고 `break`.

4) 조건식의 진실값

C에서 **0은 false**, **0이 아닌 모든 값은 true**.

c
if (count) { ... }        // count != 0 과 같음
if (ptr)   { ... }        // ptr != NULL 과 같음 (관용 표현)

예제로 보기

예제 1 — `ex01_if.c` : 점수 → 등급

c
if (score >= 90)      printf("등급: A\n");
else if (score >= 80) printf("등급: B\n");
else if (score >= 70) printf("등급: C\n");
else if (score >= 60) printf("등급: D\n");
else                  printf("등급: F\n");

**입력**: `85`

text
점수 입력 (0~100): 등급: B

**입력**: `59`

text
점수 입력 (0~100): 등급: F

핵심: 가지가 위에서 평가되므로 **순서가 중요**합니다. `if (score >= 60)` 을 가장 위로 옮기면 90점도 D가 되어버립니다.

예제 2 — `ex02_ternary.c` : 삼항 연산자

c
int max = (a > b) ? a : b;
int min = (a < b) ? a : b;
const char *parity = (a % 2 == 0) ? "짝수" : "홀수";

**입력**: `7 3`

text
두 정수 입력: 최댓값: 7
최솟값: 3
a는 홀수

핵심: 삼항은 **값**을 만들기 때문에 변수 초기화에 바로 쓸 수 있습니다.

예제 3 — `ex03_switch.c` : 사칙연산 계산기

c
switch (op) {
    case '+': result = a + b; break;
    case '-': result = a - b; break;
    case '*': result = a * b; break;
    case '/': /* 0 검사 후 a/b */ break;
    default:  /* 오류 */
}

**입력**: `12 + 5`

text
식 입력 (예: 3 + 4): 결과: 17.000

**입력**: `10 / 0`

text
식 입력 (예: 3 + 4): 0으로 나눌 수 없습니다.

핵심: `case` 라벨은 **정수형 상수**여야 합니다(문자도 정수). 문자열은 못 씁니다.

예제 4 — `ex04_nested_if.c` : 중첩 if (윤년 판정)

윤년 규칙: `4의 배수, 단 100의 배수는 제외, 400의 배수는 다시 포함`.

**입력**: `2024`

text
연도 입력: 2024년은 윤년입니다.

**입력**: `2100`

text
연도 입력: 2100년은 윤년이 아닙니다.

핵심: 중첩이 깊어지면 가독성이 급격히 떨어집니다. 한 번에 한 층까지가 좋습니다.

다른 시각으로 보기 — `if-else if`는 사실 중첩 `if`

c
if (score >= 90)
    /* A */
else if (score >= 80)
    /* B */
else
    /* C 이하 */

는 사실 다음과 똑같습니다.

c
if (score >= 90) {
    /* A */
} else {
    if (score >= 80) {
        /* B */
    } else {
        /* C 이하 */
    }
}

`else if`는 가독성을 위한 **관용적 표기**일 뿐, 별도 키워드가 아닙니다.

자주 하는 실수

  1. **`==`와 `=` 혼동**: `if (x = 0)` 는 항상 false + 사이드 이펙트.
  2. **세미콜론 혼자**: `if (x > 0);` 처럼 세미콜론을 잘못 찍으면 빈 분기.
  3. **`break` 누락**: `switch`에서 의도치 않은 fall-through.
  4. **부동소수 동등 비교**: `if (a == 0.1)` 은 거의 항상 false. 오차를 허용해 비교(`fabs(a - 0.1) < 1e-9`).
  5. **`else`가 가까운 `if`에 묶임**: 중첩 시 중괄호 없이 쓰면 의도와 다른 `if`에 붙을 수 있습니다. **항상 중괄호**를 권장.

정리

  • `if`/`else if`/`else`는 위에서 아래로 평가하므로 조건 순서가 중요.
  • 삼항 `?:`는 한 줄 분기에서 변수 초기화에 유용.
  • `switch`/`case`는 정수형(문자 포함) 분기에만 사용. `break` 잊지 말 것.
  • 조건식에서 0은 거짓, 0이 아닌 모든 값은 참.
  • 중첩이 깊어지면 함수로 분리하거나 가지를 평탄화하자.

직접 해 보기

bash
cd src
gcc -std=c11 -Wall -o ex01 ex01_if.c        && echo 85   | ./ex01
gcc -std=c11 -Wall -o ex02 ex02_ternary.c   && echo "7 3" | ./ex02
gcc -std=c11 -Wall -o ex03 ex03_switch.c    && echo "12 + 5" | ./ex03
gcc -std=c11 -Wall -o ex04 ex04_nested_if.c && echo 2000 | ./ex04

응용:

  • `ex03_switch.c`에서 `'+': result = a + b;` 의 `break`를 지워 보세요. 출력이 어떻게 달라지는지 관찰.
  • `ex01_if.c`의 등급 분기 조건을 `<= 89`처럼 거꾸로 작성해 같은 결과를 내 보세요.

💻 예제 (examples)

실제로 컴파일·실행해 결과를 확인할 수 있는 예제입니다.

ex01_if.c점수 → 등급
CODE
#include <stdio.h>

int main(void) {
    int score;
    printf("점수 입력 (0~100): ");
    scanf("%d", &score);

    if (score < 0 || score > 100) {
        printf("범위를 벗어났습니다.\n");
        return 1;
    }

    if (score >= 90)      printf("등급: A\n");
    else if (score >= 80) printf("등급: B\n");
    else if (score >= 70) printf("등급: C\n");
    else if (score >= 60) printf("등급: D\n");
    else                  printf("등급: F\n");

    return 0;
}
ex02_ternary.c삼항 연산자
CODE
#include <stdio.h>

int main(void) {
    int a, b;
    printf("두 정수 입력: ");
    scanf("%d %d", &a, &b);

    int max = (a > b) ? a : b;
    int min = (a < b) ? a : b;
    const char *parity = (a % 2 == 0) ? "짝수" : "홀수";

    printf("최댓값: %d\n", max);
    printf("최솟값: %d\n", min);
    printf("a는 %s\n", parity);

    return 0;
}
ex03_switch.c사칙연산 계산기
CODE
#include <stdio.h>

int main(void) {
    double a, b, result = 0;
    char op;

    printf("식 입력 (예: 3 + 4): ");
    scanf("%lf %c %lf", &a, &op, &b);

    int ok = 1;
    switch (op) {
        case '+': result = a + b; break;
        case '-': result = a - b; break;
        case '*': result = a * b; break;
        case '/':
            if (b == 0) { printf("0으로 나눌 수 없습니다.\n"); ok = 0; }
            else result = a / b;
            break;
        default:
            printf("지원하지 않는 연산자: %c\n", op);
            ok = 0;
    }

    if (ok) printf("결과: %.3f\n", result);
    return 0;
}
ex04_nested_if.c중첩 if (윤년 판정)
CODE
#include <stdio.h>

/* 윤년 판정: 4의 배수, 단 100의 배수는 제외, 400의 배수는 포함 */
int main(void) {
    int year;
    printf("연도 입력: ");
    scanf("%d", &year);

    int leap;
    if (year % 4 == 0) {
        if (year % 100 == 0) {
            leap = (year % 400 == 0);
        } else {
            leap = 1;
        }
    } else {
        leap = 0;
    }

    printf("%d년은 %s\n", year, leap ? "윤년입니다." : "윤년이 아닙니다.");
    return 0;
}

📝 과제 (exercises)

직접 풀어보고, 막힐 때 정답을 펼쳐 비교해보세요.

과제 1

문제 1 (hw01.c)

목표: 세 정수 a, b, c를 입력받아 **가장 큰 값**을 출력하세요.

요구사항
  • 파일명: hw01.c
정답 코드 펼치기 / 접기
SOLUTION
#include <stdio.h>

int main(void) {
    int a, b, c;
    printf("세 정수 입력: ");
    scanf("%d %d %d", &a, &b, &c);

    int max = a;
    if (b > max) max = b;
    if (c > max) max = c;

    printf("최댓값: %d\n", max);
    return 0;
}
과제 2

문제 2 (hw02.c)

목표: 사용자 나이를 입력받아 다음 메시지 중 하나를 출력하세요. - `0~7`: "유아" - `8~13`: "어린이" - `14~19`: "청소년" - `20~64`: "성인" - `65 이상`: "노인"

요구사항
  • 파일명: hw02.c
정답 코드 펼치기 / 접기
SOLUTION
#include <stdio.h>

int main(void) {
    int age;
    printf("나이 입력: ");
    scanf("%d", &age);

    if (age < 0)        printf("잘못된 입력\n");
    else if (age <= 7)  printf("유아\n");
    else if (age <= 13) printf("어린이\n");
    else if (age <= 19) printf("청소년\n");
    else if (age <= 64) printf("성인\n");
    else                printf("노인\n");

    return 0;
}
과제 3

문제 3 (hw03.c)

목표: 1~12 사이의 월(month)을 입력받아 해당 월의 **일수**를 출력하세요. 2월은 28일로 단순 처리. `switch`-fallthrough를 활용해 보세요.

요구사항
  • 파일명: hw03.c
정답 코드 펼치기 / 접기
SOLUTION
#include <stdio.h>

int main(void) {
    int month;
    printf("월(1~12) 입력: ");
    scanf("%d", &month);

    int days;
    switch (month) {
        case 1: case 3: case 5: case 7:
        case 8: case 10: case 12:
            days = 31; break;
        case 4: case 6: case 9: case 11:
            days = 30; break;
        case 2:
            days = 28; break;
        default:
            printf("잘못된 입력\n");
            return 1;
    }

    printf("%d월은 %d일입니다.\n", month, days);
    return 0;
}
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗