3-1. 키오스크 재고 관리 시스템

문제설명

카페 키오스크에는 3가지 메뉴(아메리카노, 라떼, 모카)를 조회하고 주문할 수 있다.

 

관리자는 메뉴 항목별 재고와 가격을 등록한다. 예를 들어, 각 메뉴 항목의 재고와 가격은 배열에 저장한다.

  • 아메리카노: 재고 3개, 가격 3000원
  • 라떼: 재고 3개, 가격 4000원
  • 모카: 재고 3개, 가격 4500원

사용자가 메뉴를 조회한 뒤 항목 번호와 주문 개수를 입력하면, 주문 내역(항목, 개수, 금액, 전체 금액)을 출력하고 재고를 감소시킨다. 재고보다 많은 수량을 주문하거나 재고가 0이면 "품절"을 출력한다. 이 과정을 사용자가 0을 입력할 때까지 반복한다. 


목표

  • 전역변수(global), static 변수 사용
  • const 상수 사용 (상수 정의 대신 #define MENU_COUNT 3 사용)
  • 배열과 반복문과 조건문 함께 사용
  • 재고 및 가격 관리

요구사항

 

  • 키오스크 메뉴 항목은 3개로 고정되어 있다. 
  • 키오스크 메뉴 항목 3개를 입력받고, 각각의 금액과 재고도 입력받는다. 
  • 메뉴명과 재고는 배열로 받고, 프로그램 전체에서 사용할 수 있다.
  • 주문 횟수를 관리하여 재고처리를 한다.
  • 메뉴 번호가 1~3이면 아메리카노, 라떼, 모카순으로 주문 처리
  • 재고가 0이면 "품절"을 출력하고 주문되지 않음
  • 0을 입력하면 종료

 

출력예시

1. 아메리카노 - 3000원 (재고: 3)
2. 라떼 - 4000원 (재고: 3)
3. 모카 - 4500원 (재고: 3)
0. 종료
선택할 메뉴 번호 입력: 2
주문 개수 입력: 2

주문 내역
항목: 라떼
개수: 2
금액: 8000원
전체금액: 8000원
1. 아메리카노 - 3000원 (재고: 3)
2. 라떼 - 4000원 (재고: 1)
3. 모카 - 4500원 (재고: 3)
0. 종료
선택할 메뉴 번호 입력: 2
주문 개수 입력: 2
품절
 
선택할 메뉴 번호 입력: 0
프로그램 종료
 

코드예시

더보기
더보기
#include <stdio.h>

#define MENU_COUNT 3

char menu_names[MENU_COUNT][20];
int prices[MENU_COUNT];
int stock[MENU_COUNT];

void print_menu(void)
{
    printf("\n===== 메뉴 =====\n");

    for (int i = 0; i < MENU_COUNT; i++) {
        printf("%d. %s - %d원 (재고: %d)\n",
               i + 1, menu_names[i], prices[i], stock[i]);
    }

    printf("0. 종료\n");
}

void order_menu(int menu_number, int quantity)
{
    static int total_sales = 0;

    int index = menu_number - 1;
    int cost;

    if (stock[index] < quantity) {
        printf("품절\n");
        return;
    }

    stock[index] -= quantity;

    cost = prices[index] * quantity;
    total_sales += cost;

    printf("\n주문 내역\n");
    printf("항목: %s\n", menu_names[index]);
    printf("개수: %d\n", quantity);
    printf("금액: %d원\n", cost);
    printf("전체금액: %d원\n", total_sales);
}

int main(void)
{
    int menu_number;
    int quantity;

    printf("=== 관리자 메뉴 등록 ===\n");

    for (int i = 0; i < MENU_COUNT; i++) {
        printf("%d번 메뉴 이름 입력: ", i + 1);
        scanf("%s", menu_names[i]);

        printf("%d번 메뉴 가격 입력: ", i + 1);
        scanf("%d", &prices[i]);

        printf("%d번 메뉴 재고 입력: ", i + 1);
        scanf("%d", &stock[i]);
    }

    while (1) {
        print_menu();

        printf("선택할 메뉴 번호 입력: ");
        scanf("%d", &menu_number);

        if (menu_number == 0) {
            printf("프로그램 종료\n");
            break;
        }

        if (menu_number < 1 || menu_number > MENU_COUNT) {
            printf("잘못된 메뉴 번호입니다.\n");
            continue;
        }

        printf("주문 개수 입력: ");
        scanf("%d", &quantity);

        if (quantity <= 0) {
            printf("주문 개수는 1개 이상이어야 합니다.\n");
            continue;
        }

        order_menu(menu_number, quantity);
    }

    return 0;
}
 
 
 

 

 

3-4. 게임 아이템 상점 관리

 

문제설명

게임 상점에는 아이템이 있다. 관리자는 아이템 이름, 가격, 재고를 입력하여 등록한다. 예를 들어 관리자가 다음과 같이 입력할 수 있다.

1번 아이템: Potion, 300원, 재고 5개
2번 아이템: Sword, 1000원, 재고 2개
3번 아이템: Shield, 800원, 재고 1개
...
 

사용자는 상점에서 아이템 번호와 구매 개수를 입력하여 아이템을 구매할 수 있다. 구매가 성공하면

  • 아이템 이름
  • 구매 개수
  • 구매 금액
  • 전체 누적 구매 금액

을 출력하고, 재고를 감소시킨다. 재고보다 많이 구매하려 하면 "재고 부족"을 출력한다. 이 과정을 사용자가 0을 입력할 때까지 반복하시오.

 

목표

  • 배열에 문자열, 가격, 재고 등록
  • 배열 값을 읽고 수정
  • 전역변수, static 변수, 반복문, 조건문 활용
  • 등록한 정보를 프로그램에서 계속 사용

요구사항

  • 아이템 이름, 가격, 재고를 각각 배열에 저장할 것
  • 구매가 성공하면 재고를 감소시킬 것
  • 총 구매 금액은 함수 안의 static 변수로 관리할 것
  • 종료 번호는 0

출력예시

=== 아이템 등록 ===
1번 아이템 이름 입력: Potion
1번 아이템 가격 입력: 300
1번 아이템 재고 입력: 5

2번 아이템 이름 입력: Sword
2번 아이템 가격 입력: 1000
2번 아이템 재고 입력: 2
===== 상점 =====
1. Potion - 300원 (재고: 5)
2. Sword - 1000원 (재고: 2)
3. Shield - 800원 (재고: 1)
0. 종료

구매할 아이템 번호 입력: 2
구매 개수 입력: 1

구매 내역
아이템: Sword
개수: 1
금액: 1000원
전체 구매 금액: 1000원
구매할 아이템 번호 입력: 3
구매 개수 입력: 2
재고 부족

 

 

코드예시

더보기
더보기
#include <stdio.h>

#define MAX_MENU 100
#define NAME_SIZE 20

char menu_names[MAX_MENU][NAME_SIZE];
int prices[MAX_MENU];
int stock[MAX_MENU];
int menu_count = 0;

void register_menus(void);
void print_menus(void);
void order_menu(void);

void register_menus(void)
{
    int i = 0;

    while (1) {
        int stop;

        printf("\n%d번 메뉴 이름 입력: ", i + 1);
        scanf("%s", menu_names[i]);

        printf("%d번 메뉴 가격 입력: ", i + 1);
        scanf("%d", &prices[i]);

        printf("%d번 메뉴 재고 입력: ", i + 1);
        scanf("%d", &stock[i]);

        i++;
        menu_count = i;

        if (i >= MAX_MENU) {
            printf("더 이상 메뉴를 등록할 수 없습니다.\n");
            break;
        }

        printf("계속 등록하시겠습니까? (1: 계속, 0: 종료): ");
        scanf("%d", &stop);

        if (stop == 0) {
            break;
        }
    }
}

void print_menus(void)
{
    printf("\n===== 메뉴 =====\n");

    for (int i = 0; i < menu_count; i++) {
        printf("%d. %s - %d원 (재고: %d)\n",
               i + 1, menu_names[i], prices[i], stock[i]);
    }

    printf("0. 종료\n");
}

void order_menu(void)
{
    static int total_sales = 0;

    int menu_number;
    int quantity;
    int index;
    int cost;

    while (1) {
        print_menus();

        printf("선택할 메뉴 번호 입력: ");
        scanf("%d", &menu_number);

        if (menu_number == 0) {
            printf("프로그램 종료\n");
            break;
        }

        if (menu_number < 1 || menu_number > menu_count) {
            printf("잘못된 메뉴 번호입니다.\n");
            continue;
        }

        printf("주문 개수 입력: ");
        scanf("%d", &quantity);

        if (quantity <= 0) {
            printf("주문 개수는 1개 이상이어야 합니다.\n");
            continue;
        }

        index = menu_number - 1;

        if (stock[index] < quantity) {
            printf("품절\n");
            continue;
        }

        stock[index] -= quantity;
        cost = prices[index] * quantity;
        total_sales += cost;

        printf("\n주문 내역\n");
        printf("항목: %s\n", menu_names[index]);
        printf("개수: %d\n", quantity);
        printf("금액: %d원\n", cost);
        printf("전체금액: %d원\n", total_sales);
    }
}

int main(void)
{
    printf("=== 관리자 메뉴 등록 ===\n");
    register_menus();

    if (menu_count == 0) {
        printf("등록된 메뉴가 없습니다.\n");
        return 0;
    }

    order_menu();

    return 0;
}

 

2-1. 학생 점수의 총점과 평균

문제설명

5명의 학생 점수를 배열에 저장하고 총점과 평균을 구하시오.

 

목표

  • 배열의 값을 반복문으로 처리
  • 누적합 계산

요구사항

  • 점수: {80, 75, 90, 100, 85}
  • 총점과 평균을 출력할 것
  • 평균은 소수 첫째 자리까지 출력할 것

출력예시

총점: 430
평균: 86.0

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int scores[5] = {80, 75, 90, 100, 85};
    int total = 0;
    double average;

    for (int i = 0; i < 5; i++) {
        total += scores[i];
    }

    average = (double)total / 5;

    printf("총점: %d", total);
    printf("평균: %.1f", average);

    return 0;
}

 

2-2. 가장 큰 값 찾기

 

문제설명

배열에 저장된 값 중 가장 큰 값을 찾아 출력하시오.

 

목표

  • 배열 탐색
  • 최댓값 비교

요구사항

  • 배열: {12, 35, 7, 48, 21}
  • 반복문을 이용해 최댓값을 구할 것

출력예시

가장 큰 값: 48

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int arr[5] = {12, 35, 7, 48, 21};
    int max = arr[0];

    for (int i = 1; i < 5; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }

    printf("가장 큰 값: %d", max);

    return 0;
}

 

2-3. 문자열 길이 직접 세기

 

문제설명

문자열 배열에 저장된 단어의 길이를 직접 세어 출력하시오.

 

목표

  • char 배열과 '\0' 활용
  • 문자열 끝까지 반복

요구사항

  • char word[] = "APPLE";
  • strlen()을 사용하지 말 것
  • 반복문으로 글자 수를 셀 것

출력예시

문자열 길이: 5

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    char word[] = "APPLE";
    int length = 0;

    while (word[length] != '\0') {
        length++;
    }

    printf("문자열 길이: %d", length);

    return 0;
}

 

2-4. 배열 뒤집기

 

문제설명

배열의 값을 거꾸로 출력하시오.

 

목표

  • 배열의 마지막 인덱스부터 접근
  • 배열 크기와 인덱스 계산 응용

요구사항

  • 배열: {10, 20, 30, 40, 50}
  • 반복문을 이용하여 뒤에서부터 출력할 것

출력예시

50 40 30 20 10

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int arr[5] = {10, 20, 30, 40, 50};

    for (int i = 4; i >= 0; i--) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

 

2-5. 중복 없는 숫자 개수 세기

 

문제설명

배열에 저장된 숫자들 중 서로 다른 숫자가 몇 개인지 구하시오.

예를 들어 {1, 2, 2, 3, 1, 4}에는 서로 다른 숫자가 4개 있다.

 

목표

  • 배열을 여러 번 탐색하는 중첩 반복문
  • 배열 비교 응용

요구사항

  • 배열: {1, 2, 2, 3, 1, 4}
  • 서로 다른 숫자의 개수를 출력할 것
  • 새로운 배열을 사용하지 말고 해결할 것

 

출력예시

서로 다른 숫자의 개수: 4

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int arr[6] = {1, 2, 2, 3, 1, 4};
    int count = 0;
    int is_duplicated;

    for (int i = 0; i < 6; i++) {
        is_duplicated = 0;

        for (int j = 0; j < i; j++) {
            if (arr[i] == arr[j]) {
                is_duplicated = 1;
                break;
            }
        }

        if (is_duplicated == 0) {
            count++;
        }
    }

    printf("서로 다른 숫자의 개수: %d", count);

    return 0;
}

1-1. 배열 선언과 인덱스

문제설명

정수 3개를 저장하는 배열을 선언하고, 각각 10, 20, 30을 저장한 뒤 첫 번째 원소와 마지막 원소를 출력하시오.

 

목표

  • 배열 선언
  • 인덱스가 0부터 시작함을 이해

요구사항

  • int arr[3] 형태로 선언할 것
  • arr[0], arr[2]를 출력할 것

출력예시

첫 번째 값: 10
마지막 값: 30

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int arr[3] = {10, 20, 30};

    printf("첫 번째 값: %d", arr[0]);
    printf("마지막 값: %d", arr[2]);

    return 0;
}

 

1-2. 배열과 반복문

 

문제설명

배열에 저장된 5개의 정수를 반복문으로 모두 출력하시오.

 

목표

  • 배열과 for문의 결합
  • arr[i] 형태의 접근 이해

요구사항

  • 배열: {3, 6, 9, 12, 15}
  • for문으로 출력할 것

출력예시

3
6
9
12
15

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int arr[5] = {3, 6, 9, 12, 15};

    for (int i = 0; i < 5; i++) {
        printf("%d", arr[i]);
    }

    return 0;
}

 

1-3. 부분 초기화

 

문제설명

다음 배열을 선언했을 때 각 원소의 값을 출력하시오.

int arr[5] = {10, 20};

 

목표

  • 부분 초기화 시 남는 원소가 0으로 채워짐을 이해

요구사항

  • 반복문으로 5개의 원소를 모두 출력할 것

출력예시

arr[0] = 10
arr[1] = 20
arr[2] = 0
arr[3] = 0
arr[4] = 0

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int arr[5] = {10, 20};

    for (int i = 0; i < 5; i++) {
        printf("arr[%d] = %d", i, arr[i]);
    }

    return 0;
}

 

1-4. char 배열과 문자열

 

문제설명

문자 배열에 "CAT"을 저장하고 문자열로 출력하시오.

 

목표

  • char 배열과 문자열의 차이 이해
  • 문자열 끝에는 '\0' 이 필요함을 이해

요구사항

  • char word[4] = {'C', 'A', 'T', '\0' };
  • %s로 출력할 것

출력예시

CAT

 

코드예시

#include <stdio.h>

int main(void)
{
    char word[4] = {'C', 'A', 'T', '\0'};

    printf("%s", word);

    return 0;
}

 

1-5. 잘못된 인덱스 찾기

 

문제설명

다음 코드의 문제점을 설명하시오.

int arr[3] = {1, 2, 3};
printf("%d", arr[3]);

 

목표

  • 배열 범위를 벗어난 접근이 잘못됨을 이해

요구사항

  • 왜 잘못되었는지 서술할 것
  • 올바른 코드로 수정할 것

설명예시

더보기
더보기

배열의 인덱스는 0번부터 (배열의 크기-1)번까지 할당된다. 

int arr[3] = {1,2,3}; 에서는, 마지막 원소는 arr[2]이고, arr[3]은 배열 범위를 벗어난 위치이다.

 

따라서, 

int arr[3] = {1, 2, 3};
printf("%d", arr[2]);  // 3을 2로 수정한다. 

 

1-6. 배열 크기 구하기

 

문제설명

배열의 전체 바이트 수와 원소개수를 출력하시오.

 

목표

  • sizeof()를 이용한 배열 크기 계산

요구사항

  • 배열: int arr[5] = {10, 20, 30, 40, 50};
  • 배열의 전체 크기와 원소개수를 각각 출력할 것

출력예시

배열 전체 크기: 20
원소개수: 5

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    int arr[5] = {10, 20, 30, 40, 50};
    int total_size = sizeof(arr);
    int count = sizeof(arr) / sizeof(arr[0]);

    printf("배열 전체 크기: %d", total_size);
    printf("원소개수: %d", count);

    return 0;
}

 

1-7. 문자열 입력받기

 

문제설명

사용자의 이름을 문자열로 입력받아 그대로 출력하시오.

 

목표

  • char 배열에 문자열 저장
  • scanf("%s", ...) 사용

요구사항

  • char name[20];으로 선언할 것
  • 이름을 입력받아 다시 출력할 것
 
출력예시
이름 입력: Luna
입력한 이름: Luna

 

코드예시

더보기
더보기
#include <stdio.h>

int main(void)
{
    char name[20];

    printf("이름 입력: ");
    scanf("%s", name);

    printf("입력한 이름: %s\n", name);

    return 0;
}
 

클래스 수준의 속성/메서드 VS 인스턴스 수준의 속성/메서드

 

클래스의 구성요소인 속성(attribute)과 메서드(method)는 클래스를 구현하고 실행하여 인스턴스를 생성하고 사용하는 과정에서 클래스 수준에서 사용되는 속성과 메서드, 그리고 인스턴스 수준에서 사용되는 속성과 메서드로 구분할 수 있다.

 

  인스턴스 수준 클래스 수준
속성 (Attribute) 각각의 인스턴스가 가진 고유값 여러 인스턴스가 같은 값을 공유
매서드 (Method) 인스턴스에서 호출할 수 있는 메서드
인스턴스 값을 핸들링
클래스 속성을 수정하거나 클래스 레벨에서 공통적으로 관리하는 동작을 수행할 때 사용

 

인스턴스 수준의 속성은 각각의 인스턴스가 자신의 고유값을 갖는다. 그리고 이 고유의 값을  즉 인스턴스 하나를 인식하고 그 값을 핸들링(초기화, 수정, 삭제 등) 하는 메서드를 인스턴스 메서드라 한다. 반면에 클래스 수준의 속성은 클래스의 모든 인스턴스가 한 값을 공유한다. 그리고 이 값을 핸들링 하는 매서드를 클래스 매서드라 한다. 

 

예를 들어 고양이 클래스에서 모든 고양이 인스턴스들을 고양이과에 속한다. 그래서 species(종) 속성은 '고양이과'라는 모든 인스턴스가 공유하는 값을 가진다. 그리고 이 값을 리턴하는 클래스 수준의 매서드 getSpecies()를 정의한다. 

 

위 구조를 파이썬 코드로 구현하면 아래와 같다. 

class Cat:
    __species = "고양이과"  # 클래스 변수
    def __init__(self, name, color, size, gender, breed):
        self.__name = name
        self.__color = color
        self.__size = size
        self.__gender = gender
        self.__breed = breed
    def get_name(self): return self.__name
    def get_color(self): return self.__color
    def get_size(self): return self.__size
    def get_gender(self): return self.__gender
    def get_breed(self): return self.__breed
    
    def meow(self):
        print(f"{self.__name}: 야옹!") 
    
    @classmethod
    def get_species(cls): return cls.__species
 
# 인스턴스 생성
cat1 = Cat("구글링_고양이1", "고등어/흰색", "중형", "암컷", "코숏")
cat2 = Cat("봄비", "카오스", "중형", "암컷", "코숏")
cat3 = Cat("쿠키", "치즈냥이", "중형", "수컷", "코숏")
 
# 정보 출력
for cat in [cat1, cat2, cat3]:
    print("이름:", cat.get_name())
    print("색상:", cat.get_color())
    print("크기:", cat.get_size())
    print("성별:", cat.get_gender())
    print("품종:", cat.get_breed())
    print("종:", cat.get_species())
    print("종:", Cat.get_species())
    
    cat.meow()
    print()

 

  • 클래스 수준의 속성 정의 : 위 코드에서는 2라인의 __species라는 속성이 클래스 수준의 속성으로 정의되었다.  즉, 생성된 Cat 클래스의 인스턴스는 모두 __species라는 속성을 가지고 그 값은 "고양이과" 이다. 
  • 클래스 수준의 속성 사용(getter 정의): 클래스 밖에서 클래스 수준의 속성인 __species를 사용하기 위해 get_species(cls) 메소드를 @classmethod 데코레이터를 사용하여 정의하였다. 클래스 수준의 메소드는 인스턴스 수준의 메소드와 달리 self 가 아닌 class의 약자인 cls를 파라메터로 받는다. 
  • 클래스 수준의 getter 사용: 클래스 밖에서 get_species( )인 클래스 수준의 메소드를 호출할 때는 생성한 Cat 타입의 인스턴스를 받는 cat변수의 cat.get_species()를 호출해도 되고, 클래스 명 자체를 붙여 Cat.get_species()를 호출해도 된다. 

또 다른 예로,  도서관 시스템의 예에서도 BookLoan 클래스에 아래와 같은 도서대출 1,2,3의 인스턴스를 생성할 수 있다. 도서 대출 클래스의 클래스 수준 속성은 아래와 같다.

  • max_loan_days: 도서대출 기간이 2주라고 한다면 모든 도서대출 인스턴스가 도서대출 신청한 날짜에 2주후로 due_date 값을 계산해야 한다. 즉, 모든 인스턴스가 max_loan_days의 값을 공유한다. 
  • book_loan_list: 고양이의 species와 max_loan_days와 다른 리스트 형태의 클래스 수준 속성이다. 이 리스트는 BookLoan클래스 타입으로 생성된 모든 인스턴스의 리스트이다. 즉, 클래스 외부에서 book_loan1 = BookLoan( ...) 으로 클래스 인스턴스를 생성하면, BookLoan 클래스의 생성자에서 생성된 인스턴스를 해당 리스트에 append()한다. 따라서 BookLoan 클래스 밖에서는 생성한 대출 클래스의 인스턴스 전체를 book_loan_list 에서 찾을 수 있다. 

 

이를 파이썬 코드로 구현하면 아래와 같다. 

class BookLoan:
    __max_loan_days = 14          # 클래스 변수
    __book_list = []              # 클래스 변수: 전체 대출 목록
 
    def __init__(self, loan_id, book, user, loan_date):
        self.__id = loan_id
        self.__book = book
        self.__user = user
        self.__loan_date = loan_date
        self.__due_date = f"{loan_date} + {BookLoan.__max_loan_days}일"
        self.__return_date = "0000-00-00"
        self.__status = "Borrowed"
 
        # 생성된 객체를 클래스 변수 BookList에 추가
        BookLoan.__book_list.append(self)
 
    def borrow_book(self):
        print(f"{self.__user}가 {self.__book}을(를) 대출했습니다.")
 
    def return_book(self, return_date):
        self.__return_date = return_date
        self.__status = "Returned"
        print(f"{self.__book} 반납 완료")
 
    def extend_loan(self, days):
        print(f"대출 기간 {days}일 연장")
 
    def check_status(self):
        print(f"[{self.__id}] {self.__book} / {self.__status}")
 
    @classmethod
    def get_max_loan_days(cls):
        return cls.__max_loan_days
 
    @classmethod
    def print_book_list(cls):
        print()
        print("========== 전체 대출 목록 ==========")
        for loan in BookLoan.__book_list:
            loan.check_status()
        print()
 
 
# 객체 생성
loan1 = BookLoan("BL20250305001", "BKH001", "ST240101", "2025-03-05")
loan2 = BookLoan("BL20250305002", "BKSC001", "ST191101", "2025-03-05")
loan3 = BookLoan("BL20250305003", "BKE001", "ST200101", "2025-03-05")
 
# 전체 대출 목록 출력
BookLoan.print_book_list();
 
print("최대 대출 기간:", BookLoan.get_max_loan_days(), "일")

 

  • 3라인 클래스 수준의 속성 생성:  클래스 수준의 속성으로 __book_list를 리스트 타입으로 정의하였다.
  • 15라인 리스트에 인스턴스 대입: 클래스 인스턴스 생성시, 즉 생성자 __init__()에서 self 인스턴스가 만들어지면 __book_list.append(self)로 __book_list에 해당 인스턴스를 append 한다. 
  • 35 ~ 41라인 __book_list의 인스턴스 목록을 출력
  • 50 라인 생성된 BookLoan의 __book_list 목록을 출력하는 클래스 수준의 메서드를 호출한다. 

객체지향 프로그래밍에서 클래스를 정의하는 중요하게 적용되는 특징 4가지가 있다. 캡슐화(Encapsulation), 정보은닉(Information Hiding), 상속(Inheritance), 그리고 다형성(Polymorphism) 이다. 이번 장에서는 마지막 네번째 특징인 다형성의 개념을 살펴본다. 

다형성(Polymorphism)의 개념

Polymorphism 이라는 단어는 그리스어에서 유래한 단어로 Poly(‘많음’, '여러가지 의미), Morph("형태, 모습, Form, Shape), ~ism("특징, 상태,Condition, State) 의 합성어이다. 즉, 여러 가지 형태를 가질 수 있는 특징, 상태 를 의미한다. 
일반적인 객체지향 프로그래밍에서는 다형성을 변수(참조 변수)의 타입과, 실제 메모리에 생성되어 바인딩된 객체의 타입이 서로 다를 수 있다는 관점에서 설명하고, 프로그래밍 언어에서 이를 구현하기 위한 장치들을 설명한다. 그러나 파이썬에서의 다형성(Polymorphism)은 변수의 타입을 엄격히 정의하지 않고, 객체가 실제로 수행할 수 있는 동작을 중요하게 보기 때문에, 다형성은 메서드 오버라이딩, 덕 타이핑, 연산자 오버로딩을 통해 이해할 수 있다. 
1. 메소드 오버라이딩(Method Overriding) - ­하나의 메서드 이름이 다양한 자식 클래스의 다양한 구현, ­실행시 한 변수에 다양한 자식 클래스 인스턴스가 대입되면서 매서드의 다형성이 나타난다.
2. Duck Type - ­상속관계가 아니어도 필요한 메서드나 속성을 가지고 있으면 같은 방식으로 사용할 수 있다.
3. 오퍼레이터 오버로딩(Operator Overloading) - ­일반적인 오퍼레이터(+,-,*,/)의 의미가 적용되는 클래스에 따라 재정의된다. 

 

1. 메소드 오버라이딩(Method Overriding)

상속 구조에서 특정 메소드의 내부구현(로직)Polymorphic 하게 수행되는 것을 의미한다. 예를 들어 Mammal 클래스의 speak()을 Cat 클래스와 Dog 클래스에서 상속받아 각자의 특성에 맞게 재정의한 후, 호출 할 수 있다. 

 

이와 같은 메소드 오버라이딩을 코드로 구현하면 아래와 같은데, 여기서 집중해야 할 곳은 13라인 부터이다. 

class Mammal:
    def speak(self): # 부모 클래스의 메서드
        print("It makes its own sound.")

class Dog(Mammal):
    def speak(self): # 메서드 오버라이딩
        print("Woof!")

class Cat(Mammal):
    def speak(self): # 메서드 오버라이딩
        print("Meow!")
    
animalList = [Dog(), Cat(), Mammal()]
for animal in animalList:
    animal.speak()

 

  • 13라인 - animalList라는 리스트 타입의 변수에 Dog(), Cat(), Mammal() 클래스의 인스턴스를 각각 하나씩 생성하여 넣어준다. 
  • 14라인 - animalList의 인스턴스들을 animal 변수에 하나씩 대입해서 for문을 실행한다.
  • 15라인 animal.speak()을 호출한다. 이때, animal 변수에 대입된 인스턴스의 타입에 따라 Dog.speak()이 실행된지, Cat.speak()이 실행될지, Mammal.speak()이 실행될지가 결정된다. 따라서 anmial.speak()은 polymorphic하다.

 

2. 덕타입핑(Duck Typing)

 

파이썬에서 Duck Typing(덕 타이핑)은 객체의 클래스나 상속 관계보다, “그 객체가 필요한 메서드나 기능을 가지고 있는가?”를 기준으로 사용하는 방식이다. 

“오리처럼 걷고, 오리처럼 소리내면 오리로 본다.”
→ 객체의 실제 타입보다, 필요한 동작을 할 수 있으면 같은 종류로 취급한다.

 

 

클래스 다이어그램으로 표현하면 아래와 같은데, 아래의 각 클래스들은 speak() 메소드를 모두 가지고 있다. Mammal에서 상속받은 Cat, Dog 클래스의 speak()은 재정이 되어도, speak()으로 호출되고 인스턴스에 따라 서로 다른 speak()이 실행된다는 것은  상속관계와 오버라이딩으로 통한 다형성으로 이해될 수 있다. 그런데 덕타이핑은 Robot 클래스와 같이 상속관계로 연관되지 않은 클래스도 speak()이라는 메소드가 있으면 이를 하나의 변수에 대응되어 호출 될 수 있음을 의미한다. 

 
위 클래스 다이어그램을 파이썬 코드로 구현하면 아래와 같다. 
class Mammal:
    def speak(self): 
        print("It makes its own sound.")

class Dog(Mammal):
    def speak(self):
        print("Woof!")

class Cat(Mammal):
    def speak(self):
        print("Meow!")
    
class Robot:
    def speak(self):
        print("Beep! Hello.")

def make_sound(speaker):
    speaker.speak()

dog = Dog()
cat = Cat()
robot = Robot()

make_sound(dog)
make_sound(cat)
make_sound(robot)

 

  • 1~15라인: 클래스 다이어그램에 정의된 클래스들의 구현이다. 
  • 17-18라인: speaker를 파라메터로 받는 make_sound() 함수로 speaker.speak()을 호출한다. 여기서 다형성이 이루어 지는데, speaker 변수에 어떤 타입의 인스턴스가 대입되던지, speak()이라는 메소드가 있으면 이를 수행해 줄 수 있다. 
  • 20~22라인: 각 클래스의 인스턴스를 생성한다. 
  • 24~26라인: Mammal과 상속관계에 잇는 Dog, Cat 클래스의 인스턴스와 전혀 상관없는 Robot 클래스의 인스턴스를 make_sound()함수의 인자로 넘겨준다. 세 인스턴스의 speak()함수가 호출될 것을 예상한다
3. 연산자 오버로딩(Operator Overloading)
1 + 2 = 3 이다. + 연산자는 +연산자 앞의 수와 뒤의 수 값을 더하는 기능이다. 이러한 수에서의 일반적인 기능을 사용자가 정의한 클래스에 적용한다면 어떻게 될까? Dog 클래스의 인스턴스 dog과 Cat 클래스의 인스턴스 cat을 더한다면?
 
dog + cat = ?
­
이렇게 일반적인 연산자(+, -, , == )클래스에서 적용되도록 재정의 하는것을 연산자 오버로딩(Operator Overloading)이라 한다.  아래 코드는 Mammal 이라는 클래스에 연산자 오버로딩을 구현한 예 이다. 
class Mammal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __add__(self, other):  #  나이 합치기
        return Mammal(self.name + "-" + other.name, self.age + other.age)

    def __sub__(self, other):  #  나이 차이 빼기
        return Mammal(self.name + "-분리", abs(self.age - other.age))

    def __mul__(self, num): #  나이에 수 곱하기
        return Mammal(self.name, self.age * num)
   
    def __str__(self):
        return f"{self.name} (나이: {self.age})"

dog = Mammal("바둑이", 5)
cat = Mammal("나비", 3)

print(dog + cat) #  "바둑이-나비 (나이: 8)"
print(dog - cat) #  "바둑이-분리 (나이: 2)"
print(dog * 2)   #  "바둑이 (나이: 10)"
 
재정의한 연산자는 +, -, x 이다. Mammal 클래스에서 +, -, x는 이름은 연결하고, 나이를 +, -, x 한 새로운 Mammal 인스턴스를 생성하는 것으로 정의하였다. 
 
연산자를 재정의하기 위해서 +는 __add__() 함수로, -는 __sub__() 함수로, x는 __mul__()함수로 구현한다. (파이썬 규칙)
  • 6라인:  + 연산자를 구현한다. 두 인스턴스의 이름을 연결하고, 나이도 합친다. 
  • 9라인: - 연산자를 구현한다.  두 인스턴스의 이름을 연결하고, 나이는 차를 구한다.   
  • 12라인: x 연산자를 구현한다.  두 인스턴스의 이름을 연결하고, 나이는 곱해준다. 
  • 15라인: Mammal 클래스의 인스턴스를 print()하거나 str()으로 표현할때 호출 되는 함수를 재정의 한다.
    •  __str__()은 객체를 문자열로 표현할 때 자동으로 호출되는 특별 메서드(special method)이다.
    • 객체를 print() 하거나 str()로 변환하면, 파이썬은 내부적으로 __str__()을 호출된다.
    • Mammal 클래스의 인스턴스를 print()하거나 str()으로 표현할때 호출 되는 함수를 재정의 한 것이다. (오퍼레이터 오버로딩으로 부르지는 않음)
  • 21~23라인
    • dog + cat, dog - cat, dog * 2를 수행하면 재정의된 __add__(), __sub__(), __mul__()이 호출되어 새로 생성된 Mammal클래스 타입의 인스턴스가 리턴된다. 
    • 리턴된 인스턴스를 print()하면 __str__()이 호출되어 name과 age가 string으로 반환되어 출력된다. 
 
 

3-1. 메뉴 주문 누적 통계 프로그램

문제설명

카페에서 메뉴 주문을 계속 입력받아 주문을 처리하고, 종료 시 총 주문 횟수, 총 매출, 가장 많이 주문된 메뉴를 출력하는 프로그램을 작성하시오.

 

목표

  • 반복문 안에서 메뉴 처리
  • 조건문으로 예외 처리
  • 여러 함수 호출 구조 설계
  • 누적 데이터 관리

요구사항

  1. 메뉴는 다음과 같다.
    • 1: 아메리카노 (2000원)
    • 2: 라떼 (3000원)
    • 3: 모카 (3500원)
    • 0: 종료
  2. 메뉴 번호와 수량을 입력받아 주문 처리하시오.
  3. 잘못된 메뉴 번호는 무시하고 오류 메시지를 출력하시오.
  4. 수량은 1 이상이어야 한다.
  5. 종료 시 다음을 출력하시오.
    • 총 주문 횟수
    • 총 매출
    • 가장 많이 주문된 메뉴
  6. 다음과 같은 함수로 나누어 구현하시오.
    • print_menu()
    • get_price(int menu)
    • get_menu_name(int menu)
    • process_order(...)
 

출력예시

1. 아메리카노(2000)
2. 라떼(3000)
3. 모카(3500)
0. 종료
메뉴 선택: 2
수량 입력: 3
라떼 3개 주문 완료

1. 아메리카노(2000)
2. 라떼(3000)
3. 모카(3500)
0. 종료
메뉴 선택: 0

총 주문 횟수: 1
총 매출: 9000원
가장 많이 주문된 메뉴: 라떼
 
 
코드예시
#include <stdio.h>

void print_menu(void);
int get_price(int menu);
const char* get_menu_name(int menu);
void process_order(int menu, int qty, int *total_orders, int *total_sales,
                   int *count1, int *count2, int *count3);

int main(void)
{
    int menu, qty;
    int total_orders = 0;
    int total_sales = 0;
    int count1 = 0, count2 = 0, count3 = 0;

    while (1)
    {
        print_menu();
        printf("메뉴 선택: ");
        scanf("%d", &menu);

        if (menu == 0)
        {
            break;
        }

        printf("수량 입력: ");
        scanf("%d", &qty);

        process_order(menu, qty, &total_orders, &total_sales, &count1, &count2, &count3);
    }

    printf("\n총 주문 횟수: %d\n", total_orders);
    printf("총 매출: %d원\n", total_sales);

    if (count1 >= count2 && count1 >= count3)
        printf("가장 많이 주문된 메뉴: %s\n", get_menu_name(1));
    else if (count2 >= count1 && count2 >= count3)
        printf("가장 많이 주문된 메뉴: %s\n", get_menu_name(2));
    else
        printf("가장 많이 주문된 메뉴: %s\n", get_menu_name(3));

    return 0;
}

void print_menu(void)
{
    printf("\n1. 아메리카노(2000)\n");
    printf("2. 라떼(3000)\n");
    printf("3. 모카(3500)\n");
    printf("0. 종료\n");
}

int get_price(int menu)
{
    if (menu == 1) return 2000;
    if (menu == 2) return 3000;
    if (menu == 3) return 3500;
    return -1;
}

const char* get_menu_name(int menu)
{
    if (menu == 1) return "아메리카노";
    if (menu == 2) return "라떼";
    if (menu == 3) return "모카";
    return "없음";
}

void process_order(int menu, int qty, int *total_orders, int *total_sales,
                   int *count1, int *count2, int *count3)
{
    int price = get_price(menu);

    if (price == -1)
    {
        printf("잘못된 메뉴입니다.\n");
        return;
    }

    if (qty < 1)
    {
        printf("수량은 1 이상이어야 합니다.\n");
        return;
    }

    *total_orders += 1;
    *total_sales += price * qty;

    if (menu == 1) *count1 += qty;
    else if (menu == 2) *count2 += qty;
    else if (menu == 3) *count3 += qty;

    printf("%s %d개 주문 완료\n", get_menu_name(menu), qty);
}​

3-2. 약수/소수 분석기

문제설명

정수를 여러 번 입력받아, 각 수에 대해 약수의 개수, 약수의 합, 소수 여부를 판별하는 프로그램을 작성하시오. 사용자가 0을 입력하면 종료한다.

 

목표

  • 반복 입력 처리
  • 여러 계산 함수를 조합
  • 조건 분기와 함수 호출 설계 능력 강화

요구사항

  1. 0이 입력될 때까지 반복하시오.
  2. 다음 함수를 정의하시오.
    • count_divisors(int n)
    • sum_divisors(int n)
    • is_prime(int n)
  3. 각 입력값에 대해 다음 내용을 출력하시오.
    • 약수의 개수
    • 약수의 합
    • 소수 여부
  4. 1은 소수가 아님을 반영하시오.
 
 

출력예시

정수 입력(0 종료): 7
약수의 개수: 2
약수의 합: 8
소수입니다.

정수 입력(0 종료): 12
약수의 개수: 6
약수의 합: 28
소수가 아닙니다.

정수 입력(0 종료): 0
 

 

코드예시

더보기
더보기
#include <stdio.h>

int count_divisors(int n);
int sum_divisors(int n);
int is_prime(int n);

int main(void)
{
    int n;

    while (1)
    {
        printf("정수 입력(0 종료): ");
        scanf("%d", &n);

        if (n == 0)
        {
            break;
        }

        printf("약수의 개수: %d\n", count_divisors(n));
        printf("약수의 합: %d\n", sum_divisors(n));

        if (is_prime(n))
            printf("소수입니다.\n");
        else
            printf("소수가 아닙니다.\n");

        printf("\n");
    }

    return 0;
}

int count_divisors(int n)
{
    int i, count = 0;
    for (i = 1; i <= n; i++)
    {
        if (n % i == 0)
        {
            count++;
        }
    }
    return count;
}

int sum_divisors(int n)
{
    int i, sum = 0;
    for (i = 1; i <= n; i++)
    {
        if (n % i == 0)
        {
            sum += i;
        }
    }
    return sum;
}

int is_prime(int n)
{
    if (n < 2)
    {
        return 0;
    }

    if (count_divisors(n) == 2)
    {
        return 1;
    }

    return 0;
}

2-1. 여러 점수 입력 후 최고점과 합격자 수 구하기

문제설명

학생 수 N을 입력받고 점수를 입력받아, 최고점과 **합격자 수(60점 이상)**를 함께 출력하는 프로그램을 작성하시오.

 

목표

  • 반복 입력 처리
  • 여러 조건을 동시에 다루기
  • 함수 분리로 역할 나누기

요구사항

  1. input_scores_and_process(int n, int *max_score, int *pass_count) 형태로 구현하거나, 반환 구조를 적절히 설계하시오.
  2. 최고점과 합격자 수를 모두 계산하시오.
  3. 입력 점수는 0~100 범위라고 가정하시오.
출력예시
학생 수 입력: 4
1번 학생 점수: 75
2번 학생 점수: 88
3번 학생 점수: 59
4번 학생 점수: 91
최고점: 91
합격자 수: 3
 
코드예시

 

#include <stdio.h>

void process_scores(int n, int *max_score, int *pass_count);

int main(void)
{
    int n;
    int max_score = 0;
    int pass_count = 0;

    printf("학생 수 입력: ");
    scanf("%d", &n);

    process_scores(n, &max_score, &pass_count);

    printf("최고점: %d\n", max_score);
    printf("합격자 수: %d\n", pass_count);

    return 0;
}

void process_scores(int n, int *max_score, int *pass_count)
{
    int i, score;

    for (i = 1; i <= n; i++)
    {
        printf("%d번 학생 점수: ", i);
        scanf("%d", &score);

        if (i == 1 || score > *max_score)
        {
            *max_score = score;
        }

        if (score >= 60)
        {
            (*pass_count)++;
        }
    }
}

 

2-2. ATM 메뉴 반복 처리 프로그램

 

문제설명

간단한 ATM 프로그램을 작성하시오. 사용자는 메뉴를 반복해서 선택할 수 있으며, 입금, 출금, 잔액 조회를 할 수 있다.

 

목표

  • 반복문 안에서 제어문 처리
  • 함수로 기능 나누기
  • 상태값(잔액) 갱신

요구사항

  1. 메뉴는 다음과 같다.
    • 1: 입금
    • 2: 출금
    • 3: 잔액조회
    • 0: 종료
  2. deposit, withdraw, print_balance 함수를 정의하시오.
  3. 잔액보다 큰 금액 출금 시 "잔액 부족"을 출력하시오.
  4. 종료 전까지 계속 반복하시오.
출력예시
1.입금 2.출금 3.잔액조회 0.종료
선택: 3
현재 잔액: 10000원

1.입금 2.출금 3.잔액조회 0.종료
선택: 2
출금액: 12000
잔액 부족
 
코드예시
#include <stdio.h>

void deposit(int *balance, int amount);
void withdraw(int *balance, int amount);
void print_balance(int balance);

int main(void)
{
    int menu;
    int amount;
    int balance = 10000;

    while (1)
    {
        printf("\n1.입금 2.출금 3.잔액조회 0.종료\n");
        printf("선택: ");
        scanf("%d", &menu);

        if (menu == 0)
        {
            break;
        }

        if (menu == 1)
        {
            printf("입금액: ");
            scanf("%d", &amount);
            deposit(&balance, amount);
        }
        else if (menu == 2)
        {
            printf("출금액: ");
            scanf("%d", &amount);
            withdraw(&balance, amount);
        }
        else if (menu == 3)
        {
            print_balance(balance);
        }
        else
        {
            printf("잘못된 메뉴입니다.\n");
        }
    }

    return 0;
}

void deposit(int *balance, int amount)
{
    *balance += amount;
    printf("%d원이 입금되었습니다.\n", amount);
}

void withdraw(int *balance, int amount)
{
    if (*balance >= amount)
    {
        *balance -= amount;
        printf("%d원이 출금되었습니다.\n", amount);
    }
    else
    {
        printf("잔액 부족\n");
    }
}

void print_balance(int balance)
{
    printf("현재 잔액: %d원\n", balance);
}

 

 

2-3. 숫자 맞히기 게임 (기회 제한)

 

문제설명

정답 숫자를 하나 정해두고, 사용자가 제한된 횟수 안에 숫자를 맞히는 프로그램을 작성하시오.

 

목표

  • 반복 + 조건 분기 + 함수 호출 결합
  • 상태 변화에 따라 다른 메시지 출력

요구사항

  1. 정답은 코드 안에서 미리 정하시오. 예: answer = 37
  2. 사용자는 최대 5번 입력할 수 있다.
  3. 입력값이 정답보다 작으면 "더 큰 수입니다."
  4. 입력값이 정답보다 크면 "더 작은 수입니다."
  5. 맞히면 즉시 종료하시오.
  6. 판정은 check_number(int input, int answer) 함수로 처리하시오.

출력예시

1번째 입력: 20
더 큰 수입니다.
2번째 입력: 50
더 작은 수입니다.
3번째 입력: 37
정답입니다!
 

 

예시코드

더보기
더보기
#include <stdio.h>

int check_number(int input, int answer);

int main(void)
{
    int answer = 37;
    int input;
    int i;
    int result;

    for (i = 1; i <= 5; i++)
    {
        printf("%d번째 입력: ", i);
        scanf("%d", &input);

        result = check_number(input, answer);

        if (result == 0)
        {
            printf("정답입니다!\n");
            break;
        }
        else if (result < 0)
        {
            printf("더 큰 수입니다.\n");
        }
        else
        {
            printf("더 작은 수입니다.\n");
        }
    }

    if (i == 6)
    {
        printf("실패! 정답은 %d입니다.\n", answer);
    }

    return 0;
}

int check_number(int input, int answer)
{
    if (input == answer)
    {
        return 0;
    }
    else if (input < answer)
    {
        return -1;
    }
    else
    {
        return 1;
    }
}

 

1-1. 1부터 N까지 짝수만 출력하기

문제설명

정수 N을 입력받아 1부터 N까지의 수 중에서 짝수만 출력하는 프로그램을 작성하시오.

 

목표

  • for 반복문 사용
  • if 제어문 사용
  • 함수 분리 연습

요구사항

  1. print_even_numbers(int n) 함수를 정의하시오.
  2. main()에서 N을 입력받아 함수를 호출하시오.
  3. 짝수만 한 줄에 하나씩 출력하시오.

출력예시

N 입력: 10
2
4
6
8
10
 

코드예시

더보기
더보기
더보기
더보기
#include <stdio.h>

void print_even_numbers(int n);

int main(void)
{
    int n;
    printf("N 입력: ");
    scanf("%d", &n);

    print_even_numbers(n);

    return 0;
}

void print_even_numbers(int n)
{
    int i;
    for (i = 1; i <= n; i++)
    {
        if (i % 2 == 0)
        {
            printf("%d\n", i);
        }
    }
}

 

1-2. 구구단 중 한 단 출력하기

 

문제설명

출력할 단을 입력받아 해당 구구단을 출력하는 프로그램을 작성하시오.

 

목표

  • 반복문과 조건문을 함께 사용
  • 함수 호출 구조 익히기

요구사항

  1. print_dan(int dan) 함수를 정의하시오.
  2. 2 ~ 9 사이의 값만 정상 출력하시오.
  3. 범위를 벗어나면 "잘못된 입력입니다."를 출력하시오.
출력예시
단 입력: 4
4 x 1 = 4
4 x 2 = 8
4 x 3 = 12
4 x 4 = 16
4 x 5 = 20
4 x 6 = 24
4 x 7 = 28
4 x 8 = 32
4 x 9 = 36
 
 
코드예시
더보기
더보기
더보기
더보기
#include <stdio.h>

void print_dan(int dan);

int main(void)
{
    int dan;
    printf("단 입력: ");
    scanf("%d", &dan);

    print_dan(dan);

    return 0;
}

void print_dan(int dan)
{
    int i;

    if (dan < 2 || dan > 9)
    {
        printf("잘못된 입력입니다.\n");
        return;
    }

    for (i = 1; i <= 9; i++)
    {
        printf("%d x %d = %d\n", dan, i, dan * i);
    }
}

 

1-3. 점수 여러 개 입력받아 합격 개수 세기

 

문제설명

학생 수 N을 입력받고, 각 학생의 점수를 입력받아 60점 이상인 학생 수를 출력하는 프로그램을 작성하시오.

 

목표

  • 반복 입력 처리
  • 조건 판단
  • 계산 기능 함수 분리

요구사항

  1. count_pass_students(int n) 함수를 정의하시오.
  2. n명의 점수를 입력받아 60점 이상 개수를 세시오.
  3. 최종 합격자 수를 출력하시오.
출력예시
학생 수 입력: 5
1번 학생 점수: 80
2번 학생 점수: 55
3번 학생 점수: 90
4번 학생 점수: 61
5번 학생 점수: 40
합격자 수: 3
 

 

코드예시

더보기
더보기
더보기
더보기
#include <stdio.h>

int count_pass_students(int n);

int main(void)
{
    int n;
    int result;

    printf("학생 수 입력: ");
    scanf("%d", &n);

    result = count_pass_students(n);
    printf("합격자 수: %d\n", result);

    return 0;
}

int count_pass_students(int n)
{
    int i, score, count = 0;

    for (i = 1; i <= n; i++)
    {
        printf("%d번 학생 점수: ", i);
        scanf("%d", &score);

        if (score >= 60)
        {
            count++;
        }
    }

    return count;
}

 

1-4. 메뉴 번호를 입력받아 반복 주문하기

 

문제설명

사용자가 메뉴 번호를 계속 입력하면 메뉴명을 출력하고, 0을 입력하면 종료하는 프로그램을 작성하시오.

 

목표

  • while 반복문
  • if-else 또는 switch
  • 함수 호출

요구사항

  1. print_menu_name(int menu) 함수를 정의하시오.
  2. 메뉴는 다음과 같다.
    • 1: 아메리카노
    • 2: 라떼
    • 3: 모카
  3. 0 입력 시 종료하시오.
  4. 잘못된 번호는 "없는 메뉴입니다."를 출력하시오.

출력예시

메뉴 번호 입력(0 종료): 1
아메리카노
메뉴 번호 입력(0 종료): 3
모카
메뉴 번호 입력(0 종료): 7
없는 메뉴입니다.
메뉴 번호 입력(0 종료): 0
주문을 종료합니다.

 

 

코드예시

더보기
더보기
더보기
더보기
#include <stdio.h>

void print_menu_name(int menu);

int main(void)
{
    int menu;

    while (1)
    {
        printf("메뉴 번호 입력(0 종료): ");
        scanf("%d", &menu);

        if (menu == 0)
        {
            break;
        }

        print_menu_name(menu);
    }

    printf("주문을 종료합니다.\n");
    return 0;
}

void print_menu_name(int menu)
{
    if (menu == 1)
    {
        printf("아메리카노\n");
    }
    else if (menu == 2)
    {
        printf("라떼\n");
    }
    else if (menu == 3)
    {
        printf("모카\n");
    }
    else
    {
        printf("없는 메뉴입니다.\n");
    }
}

 

1-5. 약수의 개수 구하기

 

문제설명

정수 하나를 입력받아 그 수의 약수의 개수를 구하는 프로그램을 작성하시오.

 

목표

  • 반복문으로 전체 검사
  • 조건문으로 약수 판별
  • 함수 반환값 사용

요구사항

  1. count_divisors(int n) 함수를 정의하시오.
  2. 1부터 n까지 반복하면서 약수 개수를 세시오.
  3. 결과를 출력하시오.

출력예시

정수 입력: 12
약수의 개수: 6
 
 
코드예시
더보기
더보기
더보기
더보기
#include <stdio.h>

int count_divisors(int n);

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

    printf("약수의 개수: %d\n", count_divisors(n));

    return 0;
}

int count_divisors(int n)
{
    int i, count = 0;

    for (i = 1; i <= n; i++)
    {
        if (n % i == 0)
        {
            count++;
        }
    }

    return count;
}

+ Recent posts