1-1 구조체 정의 및 사용

문제설명

구조체를 정의하고 변수 선언 및 초기화를 통해 기본 사용법을 연습하는 문제이다.

 

목표

  • 구조체 정의
  • 구조체 변수 선언 및 초기화
  • 멤버 접근

요구사항

  • struct point를 정의하시오 (멤버: xpos, ypos)
  • 변수 p1을 선언하고 {10, 20}으로 초기화하시오
  • xpos와 ypos를 출력하시오
 

출력예시

10 20
 

 

 

예상 코드

더보기
#include <stdio.h>

struct point {
    int xpos;
    int ypos;
};

int main(void) {
    struct point p1 = {10, 20};
    printf("%d %d\n", p1.xpos, p1.ypos);
    return 0;
}
 

 

1-2 구조체 배열

문제설명

구조체 배열을 사용하여 여러 개의 구조체 데이터를 다루는 문제이다.

 

목표

  • 구조체 배열 이해
  • 배열 요소 접근

요구사항

  • struct point를 정의하시오. (멤버: xpos, ypos)
  • 구조체 배열 arr[2]를 선언하고
    • (1,2), (3,4)로 초기화
  • 배열의 모든 요소를 출력하시오

출력예시

1 2
3 4
 

 

예상 답안

더보기
#include <stdio.h>

struct point {
    int xpos;
    int ypos;
};

int main(void) {
    struct point arr[2] = {{1,2}, {3,4}};

    for(int i=0; i<2; i++) {
        printf("%d %d\n", arr[i].xpos, arr[i].ypos);
    }

    return 0;
}
 

 

1-3 구조체 포인터와 -> 연산자

문제설명

구조체 포인터를 사용하여 멤버에 접근하는 방법을 연습하는 문제이다.

 

목표

  • 구조체 포인터 이해
  • (*p). vs -> 차이 이해

요구사항

  • struct point를 정의하시오. (멤버: xpos, ypos)
  • struct point p1 = {5, 6} 선언 하시오.
  • 포인터 p가 p1을 가리키도록 설정
  • 아래 두 방식으로 값을 출력하시오
    • (*p).xpos
    • p->xpos

 

출력예시

5 6
5 6
 

 

 

예상 답안

더보기
#include <stdio.h>

struct point {
    int xpos;
    int ypos;
};

int main(void) {
    struct point p1 = {5, 6};
    struct point *p = &p1;

    printf("%d %d\n", (*p).xpos, (*p).ypos);
    printf("%d %d\n", p->xpos, p->ypos);

    return 0;
}
 

1-4 구조체 내부 포인터

문제설명

구조체 멤버로 포인터를 사용하는 구조를 이해하는 문제이다.

 

목표

  • 구조체 안에 포인터 포함
  • 포인터를 통한 접근

요구사항

struct point {
    int xpos;
    int ypos;
};

struct circle {
    double radius;
    struct point *center;
};
 
  • point 변수 (3,4) 생성
  • circle 변수 생성
  • 중심 좌표 출력
 

출력예시

3 4
 

 

 

예상 답안

 
#include <stdio.h>

struct point {
    int xpos;
    int ypos;
};

struct circle {
    double radius;
    struct point *center;
};

int main(void) {
    struct point p = {3,4};
    struct circle c = {5.0, &p};

    printf("%d %d\n", c.center->xpos, c.center->ypos);

    return 0;
}
 

 

1-5 구조체 주소 개념

문제설명

구조체의 메모리 구조를 이해하는 문제이다.

 

목표

  • 구조체 주소 이해
  • 첫 번째 멤버 주소 관계 이해

요구사항

다음 코드를 작성하고 실행 결과를 관찰하시오.

struct point p = {10, 20};

printf("%p\n", &p);
printf("%p\n", &p.xpos);
 

질문) 두 값이 같은지 확인하고 이유를 설명하시오.

 

예상 답안 (설명)

더보기

두 주소는 동일하다

이유: 구조체의 시작 주소 = 첫 번째 멤버의 주소

 

1-6 typedef

문제설명

typedef를 사용하여 구조체를 간단하게 사용하는 문제이다.

 

목표

  • typedef 이해
  • struct 생략

요구사항

  • 구조체 point를 정의하고 Point로 typedef
  • 변수 선언 후 출력
 

출력예시

10 20
 

 

 

예상 답안

더보기
#include <stdio.h>

typedef struct {
    int xpos;
    int ypos;
} Point;

int main(void) {
    Point p = {10, 20};
    printf("%d %d\n", p.xpos, p.ypos);
    return 0;
}
 
 

과제 1단계. [카페 키오스크] 기능/데이타 분석, 화면 설계, 코드 템플릿 

1. 요구사항

OO 카페 키오스크 시스템은 고객이 카페 메뉴를 주문할 수 있도록 지원하는 시스템이다. 시스템은 카페에서 판매하는 메뉴 정보를 저장하고, 이를 바탕으로 메뉴 조회, 메뉴 선택, 주문 및 결제 기능을 제공한다.

카페 메뉴는 메뉴번호(menu_id), 메뉴명(name), 가격(price), 판매상태(status)를 관리한다. 판매상태는 판매중 또는 품절로 구분한다.

사용자는 키오스크 화면에서 메뉴 목록을 볼 수 있어야 하며, 메뉴명, 가격, 판매상태가 함께 표시되어야 한다. 품절인 메뉴는 선택할 수 없다.

사용자는 원하는 메뉴를 선택하고 수량을 입력하여 주문할 수 있어야 한다. 한 번의 주문에는 여러 개의 메뉴를 추가할 수 있다. 
주문이 완료되면 시스템은 주문번호(order_id), 주문한 메뉴 목록, 각 메뉴의 수량, 총 주문 금액을 저장해야 한다.

결제는 신용카드 또는 카카오페이 방식으로 진행할 수 있다. 시스템은 결제방식과 결제금액을 저장해야 한다.

결제가 완료되면 시스템은 주문번호, 주문한 메뉴명, 수량, 총 결제금액, 결제방식을 화면에 출력해야 한다.

 

2. 기능분석

1. 기능 리스트

//TODO

 

2. 데이타 리스트 - 시스템에서 생성하고 저장하는 정보

//TODO

3. 간략 설계

 

3.1 화면 메뉴 설계

//TODO

 

3.2 모듈(파일) 설계

//TODO  - optional

 

4. 코드 - 키오스크 메뉴 출력 코드 

//TODO

2-1. 키오스크 메뉴 관리 프로그램

문제설명

카페 키오스크에서는 메뉴명과 가격을 배열로 관리하고, 메뉴 목록을 확인하여, 특정 메뉴의 가격을 수정한다. 

 

목표

  • 문자열 포인터 배열을 사용하여 메뉴명을 저장할 수 있다.
  • 정수형 배열과 포인터를 함께 사용할 수 있다.
  • 포인터 연산을 이용하여 배열 값을 수정할 수 있다.
  • 반복문을 사용하여 메뉴 목록을 출력할 수 있다.
  • 함수로 기능을 분리하여 프로그램을 구현할 수 있다.

요구사항

다음 조건을 만족하는 프로그램을 작성하시오.

  1. 메뉴명 4개를 문자열 포인터 배열로 선언하시오.
    (예: Americano, Latte, Mocha, Tea)
  2. 각 메뉴의 가격을 저장할 정수형 배열을 선언하시오.
  3. 모든 메뉴를 출력하는 print_menu() 함수를 작성하시오.
    출력 형식은 아래 예시와 같이 메뉴번호, 메뉴명, 가격이 함께 출력되어야 한다.
  4. 메뉴 번호와 새로운 가격을 입력받아 해당 메뉴의 가격을 수정하는
    update_price() 함수를 작성하시오.
  5. update_price() 함수에서는 반드시
    arr[i] 방식이 아닌 포인터 연산 (*(p + i)) 을 사용하시오.
  6. 가격 수정 후 전체 메뉴를 다시 출력하시오.

출력예시

1. Americano - 3000원
2. Latte - 4000원
3. Mocha - 4500원
4. Tea - 2500원

가격을 수정할 메뉴 번호 입력: 2
새 가격 입력: 4500

수정된 메뉴 목록
1. Americano - 3000원
2. Latte - 4500원
3. Mocha - 4500원
4. Tea - 2500원
 

 

힌트

더보기

1. 배열 선언

 
char *menus[4] = {"Americano", "Latte", "Mocha", "Tea"};
int prices[4] = {3000, 4000, 4500, 2500};

 

2. print_menu() 함수

for (int i = 0; i < 4; i++) {
	printf("%d. %s - %d원\n", i + 1, menus[i], prices[i]);
}
  • 반복문 사용
  • 메뉴번호 + 메뉴명 + 가격 출력

3. update_price() 함수

int *p = prices;
*(p + (menu_number - 1)) = new_price;
  • 포인터 사용

 

 

4. main()

  • 메뉴 출력
  • 수정할 번호 입력
  • 새 가격 입력
  • 가격 수정 함수 호출
  • 수정 후 다시 출력

 

예상코드

더보기
#include <stdio.h>

#define MENU_COUNT 4

char *menus[MENU_COUNT] = {
    "Americano",
    "Latte",
    "Mocha",
    "Tea"
};

int prices[MENU_COUNT] = {
    3000, 4000, 4500, 2500
};

void print_menu(void)
{
    for (int i = 0; i < MENU_COUNT; i++) {
        printf("%d. %s - %d원\n",
               i + 1,
               menus[i],
               prices[i]);
    }
}

void update_price(int menu_number, int new_price)
{
    int *p = prices;

    *(p + (menu_number - 1)) = new_price;
}

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

    print_menu();

    printf("\n가격을 수정할 메뉴 번호 입력: ");
    scanf("%d", &menu_number);

    printf("새 가격 입력: ");
    scanf("%d", &new_price);

    update_price(menu_number, new_price);

    printf("\n수정된 메뉴 목록\n");
    print_menu();

    return 0;
}

1-1. 배열 이름과 포인터

문제설명

배열 이름이 포인터처럼 동작하는 원리를 이해하는 문제이다.

 

목표

  • 배열 이름이 첫 번째 요소의 주소임을 이해한다.

요구사항

  • 코드의 실행 결과를 쓰시오.
  • 왜 그런 결과가 나오는지 설명하시오.

코드

#include <stdio.h>

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

    printf("%d\n", *arr);
    printf("%d\n", *(arr + 2));

    return 0;
}

 

예상답안

더보기
출력예시
10
30
  • arr는 배열의 시작 주소이다.
  • *arr는 첫 번째 값 → 10
  • *(arr + 2)는 세 번째 값 → 30

 

1-2. 포인터 증가 연산

 

문제설명

포인터 증가 연산의 의미를 이해하는 문제이다.

 

목표

  • 포인터가 자료형 크기만큼 이동함을 이해한다.

요구사항

  • 실행 결과를 쓰시오.
  • p++가 무엇을 의미하는지 설명하시오.

코드

#include <stdio.h>

int main(void) {
    int arr[3] = {5, 10, 15};
    int *p = arr;

    printf("%d\n", *p);
    p++;
    printf("%d\n", *p);

    return 0;
}
 

 

예상답안

더보기
출력예시 
5
10
  • 처음에는 arr[0] → 5
  • p++ 후 arr[1] → 10
  • int형 크기만큼 다음 주소로 이동한다.
 

 

 

3-3. 문자열 포인터

문제설명

문자열 리터럴과 문자열 포인터의 관계를 이해하는 문제이다.

 

목표

  • 문자열 리터럴을 포인터가 가리킨다는 것을 이해한다.

요구사항

  • 실행 결과를 쓰시오.
  • 왜 배열처럼 접근 가능한지 설명하시오.

코드

#include <stdio.h>

int main(void) {
    char *str = "Hello";

    printf("%c\n", str[1]);

    return 0;
}
 
 
예상답안
더보기
출력예시
e
  • 문자열은 연속된 문자들의 주소를 가진다.
  • str[1]은 두 번째 문자 → e

 

3-4. 포인터 배열

문제설명

포인터 배열의 구조를 이해하는 문제이다.

 

목표

  • 배열의 각 요소가 포인터라는 것을 이해한다.

요구사항

  • 실행 결과를 쓰시오.

코드

#include <stdio.h>

int main(void) {
    char *arr[3] = {"Apple", "Banana", "Cherry"};

    printf("%s\n", arr[1]);

    return 0;
}
 
 
예상답안
더보기

출력예시

Banana
  • arr[1]은 "Banana"를 가리키는 포인터이다.

과제 1단계 수행을 위한 예제 -  콘솔 도서구매 시스템

콘솔 키오스크를 구현하기 위해 온라인 서점 도서구매 서비스로 요구사항 분석 및 설계과정을 먼저 이해합니다. 본 수업은 분석설계가 아닌 C 언어를 이해하고 프로그래밍을 목적으로 하므로, 분석, 설계 내용은 과정에 맞춰 단순화 하였습니다. 

 

1 요구사항

OO 온라인 서점 시스템은 고객이 도서를 검색하고 주문할 수 있도록 지원하는 시스템이다. 시스템은 서점에서 판매하는 도서 정보를 저장하고, 이를 바탕으로 도서 조회, 도서 선택, 주문 및 결제 기능을 제공한다.

도서는 도서번호(book_id), 도서명(title), 가격(price), 재고상태(status)를 관리한다. 재고상태는 판매중 또는 품절로 구분한다.


사용자는 온라인 서점 화면에서 도서 목록을 볼 수 있어야 하며, 도서명, 가격, 재고상태가 함께 표시되어야 한다. 품절인 도서는 화면에 표시되더라도 선택할 수 없다.


사용자는 원하는 도서를 선택하고 수량을 입력하여 주문할 수 있어야 한다. 한 번의 주문에는 여러 권의 도서를 추가할 수 있다. 주문이 완료되면 시스템은 주문번호(order_id), 주문한 도서 목록, 각 도서의 수량, 총 주문 금액을 저장해야 한다.


결제는 신용카드 또는 계좌이체 방식으로 진행할 수 있다. 시스템은 결제방식과 결제금액을 저장해야 한다.

결제가 완료되면 시스템은 주문번호, 주문한 도서명, 수량, 총 결제금액, 결제방식을 화면에 출력해야 한다.

 

2. 기능 분석

목표 시스템에서 제공해야 할 기능을 정의하고, 기능이 사용할 데이타를 구체화 한다. 

2.1. 기능 리스트 

1. 도서관리
  • 도서 등록
    도서 정보 변경
  • 도서 정보 조회(재고상태 확인 포함)
2. 주문관리
  • 주문하기
    1. 주문 항목 추가 
      • 도서 선택
      • 수량 입력
    2. 주문생성
      • 총 금액 계산
    3. 결제하기
      • 결제종류 선택하기
      • 결제진행
      • 결제 정보 저장
  • 주문 결과 출력

 

2.2. 데이타 리스트 

1. 도서정보
  • 도서번호
  • 도서명
  • 가격
  • 재고상태 (판매중, 품절)
2. 주문정보
  • 주문번호
  • 주문 항목 목록
  • 총 주문 금액
  • 주문상태
2-1. 주문정보  - 주문항목
  • 도서번호
  • 도서명
  • 수량
  • 항목 금액
4. 결제정보
  • 결제방식(신용카드, 계좌이체)
  • 결제금액
  • 결제상태

 

3.  간략 설계

3.1 화면 메뉴 설계

=========================================
온라인 도서 시스템 메뉴
========================================
도서관리              주문관리
11. 도서등록          21. 주문하기
12. 도서정보 변경     22. 주문조회
13. 도서정보 조회
=========================================

 

3.2 모듈(파일) 설계

main.c 
- main() 함수를 가지고, 프로그램 시작시 book_store_ui.c의 run()을 실행한다.

book_store_ui.c
서점 시스템의 과 메인 메뉴를 display한다. 

book_item.c
- 판매하는 도서정보를 등록, 수정, 폐기, 조회할 수 있다. 


order.c
- book_item에서 등록된 도서정보를 선택하고, 선택을 마치면 결제하여 주문 처리한다. 
-  주문완료된 정보는 주문조회 할 수 있다. 

 

 

4. 코드 템플릿

코드 예시1. 통합버전

더보기
#include <stdio.h>
 
 
void register_book(void)
{
    printf("[도서등록 기능 호출]\n");
}
 
void modify_book(void)
{
    printf("[도서정보 변경 기능 호출]\n");
}
 
void search_book(void)
{
    printf("[도서정보 조회 기능 호출]\n");
}
 
void order_book(void)
{
    printf("[주문하기 기능 호출]\n");
}
 
void search_order(void)
{
    printf("[주문조회 기능 호출]\n");
}
 
 
void print_main_menu(void)
{
    printf("=========================================\n");
    printf("        온라인 도서 시스템 메뉴\n");
    printf("=========================================\n");
    printf("도서관리               주문관리\n");
    printf("11. 도서등록           21. 주문하기\n");
    printf("12. 도서정보 변경      22. 주문조회\n");
    printf("13. 도서정보 조회\n");
    printf("0. 종료\n");
    printf("=========================================\n");
}
  
void run(void)
{
    int menu;
 
    while (1)
    {
        print_main_menu();
 
        printf("메뉴 번호를 입력하세요 (0: 종료): ");
        scanf("%d", &menu);
 
        switch (menu)
        {
            case 0:
                printf("프로그램을 종료합니다.\n");
                return;
 
            case 11:
                register_book();
                break;
 
            case 12:
                modify_book();
                break;
 
            case 13:
                search_book();
                break;
 
            case 21:
                order_book();
                break;
 
            case 22:
                search_order();
                break;
 
            default:
                printf("잘못된 메뉴 번호입니다.\n");
        }
 
        printf("\n");
    }
}
 
int main(void)
{
    run();
    return 0;
}

 

코드 예시2. 파일 분할 

더보기

main.c

/* main.c */
#include "book_store_ui.h"
 
int main(void)
{
    run();
    return 0;
}

book_store_ui.h

/* book_store_ui.h */
#ifndef BOOK_STORE_UI_H
#define BOOK_STORE_UI_H
 
void run(void);
 
#endif

  

book_store_ui.c

/* book_store_ui.c */
#include <stdio.h>
#include "book_store_ui.h"
 
void register_book(void)
{
    printf("[도서등록 기능 호출]\n");
}
 
void modify_book(void)
{
    printf("[도서정보 변경 기능 호출]\n");
}
 
void search_book(void)
{
    printf("[도서정보 조회 기능 호출]\n");
}
 
void order_book(void)
{
    printf("[주문하기 기능 호출]\n");
}
 
void search_order(void)
{
    printf("[주문조회 기능 호출]\n");
}
 
void print_main_menu(void)
{
    printf("=========================================\n");
    printf("        온라인 도서 시스템 메뉴\n");
    printf("=========================================\n");
    printf("도서관리               주문관리\n");
    printf("11. 도서등록           21. 주문하기\n");
    printf("12. 도서정보 변경      22. 주문조회\n");
    printf("13. 도서정보 조회\n");
    printf("0. 종료\n");
    printf("=========================================\n");
}
 
 
void run(void)
{
    int menu;
 
    while (1)
    {
        print_main_menu();
 
        printf("메뉴 번호를 입력하세요 (0: 종료): ");
        scanf("%d", &menu);
 
        switch (menu)
        {
            case 0:
                printf("프로그램을 종료합니다.\n");
                return;
 
            case 11:
                register_book();
                break;
 
            case 12:
                modify_book();
                break;
 
            case 13:
                search_book();
                break;
 
            case 21:
                order_book();
                break;
 
            case 22:
                search_order();
                break;
 
            default:
                printf("잘못된 메뉴 번호입니다.\n");
        }
 
        printf("\n");
    }
}

 

과제 진행 [계획]

 * 주요 활동 및 c 문법 내용을 사용에 따라 조정 가능합니다. 

주차 주제 주요 활동 핵심 C 문법
1주차 (4/30)
  요구사항 분석
기본 기능/데이터 도출
1. 요구사항 이해, 기능 / 데이타 정리
2. 기능 목록 도출 -> 화면 메뉴작성 
=>  메뉴화면 코드 개발
  변수, 자료형, 조건문, 반복문
  printf, scanf
  함수 선언(Prototype),  함수 정의
2주차 (5/7)
  데이터 구조 설계
  메뉴아이템 관리
1. MenuItem 구조체 설계, 상수 정의(#define)
2. MenuItem을 등록, 수정, 삭제, 조회 기능 개발
3. (선택)  파일 분리
=> main.c (or main.c, kiosk_ui.c/h, menu.c/h)제출
  구조체, 구조체 배열
  전역변수
  전처리기 #define
3주차 (5/14)
주문 관리1
- 메뉴 선택, 수량 입력, 주문 항목 추가
- 총액 계산, 메뉴명 복사 (Menu → OrderItem)
=> 주문 기능 개발
  배열 인덱스, 조건문, 반복문
  함수 매개변수, 반환값, Call by Value,
  배열과 포인터의 관계,  strcpy(),
4주차 (5/21)
주문 관리2
-재고 확인, 품절 처리, 재고 차감
- 결제 방식 저장, 영수증 출력
=> 결제 기능 개발
  포인터, &, *,
  Call by Reference
  정적변수
5주차 (5/28)
Heap 기반 주문 저장 
- OrderItem 배열을 malloc()으로 생성
- 주문 처리 후 free()로 메모리 해제
=>  주문관리 refactoring
malloc(), free(),
NULL 체크, 구조체 포인터, ->
6주차 (6/4)
과제 보고서 작성
시스템 통합 및 과제에 적용된 주요 C 문법/개념 정리

 

리뷰 1. 도서관 도메인에서 엔티티 클래스 설계

요구사항을 보고 서로 관련된 데이타와 기능을 encapsulation하여 Entity 클래스를 도출하고, 클래스간의 연관관계를 정의하여 클래스 설계를 완성한다. 

요구사항

OO 대학교 도서관 시스템은 학생들이 도서관 자원을 효과적으로 이용할 수 있도록, 시스템을 이용하는 사용자 정보와 도서관에서 소장하는 도서 정보를 관리하고 이를 기반으로 도서 검색, 대출, 반납, 연체 관리 기능을 제공한다.

도서관에서 소장하는 도서는 공통적으로 시스템에서 사용하는 도서의 고유 식별자, 제목, 저자, ISBN, 출판사, 출판연도, 장르 정보를 관리해야 한다. 도서는 형태에 따라 종이책(PaperBook)전자책(EBook) 으로 구분된다. 종이책은 추가적으로 서가 위치(shelf location)대출 가능한 복본 수(available copies) 를 관리해야 하며, 전자책은 파일 형식(file format), 파일 크기(file size), 동시 이용 가능 사용자 수(max simultaneous users) 를 관리해야 한다. 새로운 도서는 시스템에 등록하고, 등록된 도서는 수정, 삭제를 지원한다. 또한 등록된 도서는 키워드, 제목, 저자, 장르를 조건으로 검색할 수 있으며, 검색 결과에서는 제목, 저자, 출판사, 출판연도, 장르와 함께 도서 유형 정보를 보여준다.

도서관 시스템을 사용하는 학생은 학번, 이름, 이메일, 전화번호, 비밀번호, 전공, 선호 장르를 저장한다. 학생 정보는 신규 입력, 수정, 삭제(탈퇴)가 가능하며, 비밀번호 재설정은 현재 비밀번호를 확인한 후 수정할 수 있다.

도서를 대출하기 위해 사서는 사용자로부터 사용자 ID와 대출하려는 도서 정보를 전달받아 시스템에 사용자 ID와 도서 ID를 입력한다. 시스템은 누가(사용자 ID), 어떤 도서를(도서 ID), 언제 대출했는지를 저장한다. 대출 기한은 기본 2주(14일)이며, 한 사용자는 최대 5권까지 대출할 수 있다. 연체 중인 사용자는 새로운 도서를 대출할 수 없으며, 연체 도서를 반납한 이후에만 다시 대출할 수 있다. 종이책은 복사본 수가 남아 있을 때만 대출할 수 있고, 전자책은 동시 이용 가능 사용자 수를 초과하지 않는 범위에서 대출할 수 있다.

도서관 시스템은 매일 아침 연체 중인 사용자들에게 연체 상태 메일을 보낸다. 사용자가 대출한 도서를 사서에게 반납하면, 사서는 도서 정보를 확인하여 해당 사용자의 대출 상태를 반납 완료로 변경한다.

 

클래스 다이어그램

 

  classDiagram
    class Student {
        -userId : String
        -name : String
        -email : String
        -phone : String
        -password : String
        -major : String
        -preferredGenre : String
        +register()
        +modify()
        +delete()
        +resetPassword(currentPw, newPw)
        +hasOverdueLoans() bool
        +canBorrow() bool
    }

    class Book {
        #bookId : String
        #title : String
        #author : String
        #isbn : String
        #publisher : String
        #publishedYear : int
        #genre : String
        +register()
        +modify()
        +delete()
        +search()
    }

    class PaperBook {
        -shelfLocation : String
        -availableCopies : int
        +isAvailable() bool
    }

    class EBook {
        -fileFormat : String
        -fileSizeMB : float
        -maxSimultaneousUsers : int
        +isAvailable() bool
    }

    class BookLoan {
        -loanId : String
        -loanDate : Date
        -dueDate : Date
        -returnDate : Date
        -status : String
        +borrow()
        +returnBook()
        +isOverdue() bool
        +markReturned()
    }

    Book <|-- PaperBook
    Book <|-- EBook

    Student "1" <-- "0..5" BookLoan 
    Book "1" <-- "0..*" BookLoan 
    

  

 

 

 

 

실습 1. 키오스크 도메인에서 엔티티 클래스 다이어그램 완성하기

요구사항

OO 카페 키오스크 시스템은 고객이 카페 메뉴를 빠르고 편리하게 주문할 수 있도록 지원하는 시스템이다. 이 시스템은 카페에서 판매하는 메뉴 정보를 기본 데이터로 관리하며, 이를 기반으로 메뉴 조회 및 검색, 메뉴 선택, 주문 생성, 결제 및 주문 내역 저장 기능을 제공한다.


카페에서 판매하는 메뉴는 공통적으로 시스템에서 사용하는 메뉴의 고유 식별자(Menu ID), 메뉴명, 가격, 메뉴 설명, 판매 상태(판매중, 품절) 정보를 관리해야 한다. 메뉴는 종류에 따라 커피류(CoffeeMenu)와 디저트류(DessertMenu)로 구분된다. 커피류 메뉴는 추가적으로 원두 종류(bean type), HOT 제공 가능 여부, ICE 제공 가능 여부 정보를 관리해야 한다. 디저트류 메뉴는 추가적으로 칼로리(calories)와 알레르기 정보(allergy information)를 관리해야 한다.


사용자는 키오스크 화면에서 메뉴 목록을 조회할 수 있어야 하며, 각 메뉴에 대해 메뉴명, 가격, 판매 상태가 표시되어야 한다. 품절 상태의 메뉴는 화면에 표시되더라도 선택이 불가능해야 한다. 또한 사용자는 메뉴명이나 키워드를 이용하여 메뉴를 검색할 수 있어야 하며, 검색 결과로는 메뉴명, 가격, 메뉴 종류(커피류/디저트류) 정보가 제공되어야 한다.


사용자가 주문을 진행하기 위해 메뉴를 선택하면, 시스템은 해당 메뉴의 상세 정보를 보여주고 사용자는 수량을 선택할 수 있어야 한다. 선택한 메뉴는 주문 항목으로 추가되며, 사용자는 여러 개의 메뉴를 하나의 주문에 포함시킬 수 있어야 한다.
사용자가 주문을 확정하면 시스템은 주문을 생성하고 관련 정보를 저장해야 한다. 저장해야 할 정보에는 주문번호(고유 식별자), 주문 항목 목록(메뉴 ID, 메뉴명, 수량, 항목별 금액), 총 주문 금액, 주문 생성 시간(주문 시각), 주문 상태(예: 주문접수)가 포함된다.


주문 생성 후 사용자는 결제를 진행해야 한다. 결제는 공통적으로 결제번호, 결제금액, 결제시간, 결제상태(결제완료, 결제실패), 결제방식을 관리해야 한다. 결제 방식은 신용카드(CreditCardPayment)와 카카오페이(KakaoPayPayment)를 지원한다. 신용카드 결제는 카드사(card company)와 카드번호(card number)를 관리해야 하며, 카카오페이 결제는 카카오 계정 ID를 관리해야 한다. 하나의 주문은 하나의 결제와 연결되며, 결제가 완료되면 주문 상태는 “결제완료”로 변경된다.


주문이 정상적으로 생성되고 결제가 완료되면 키오스크는 사용자에게 주문번호와 함께 주문 내역(메뉴명, 수량, 총액, 결제방식)을 화면에 표시해야 한다.
.

 

제출. 클래스 다이어그램

 

클래스 다이어그램 예시

더보기

아래 클래스 다이어그램은 일반적인 예시 입니다. 표현의 상세도와 설계의도는 다양할 수 있습니다.

 

 

예제. [도서관 도메인] Book 클래스의 클래스 수준의 속성 정의 및 다형성 

도서관 도메인에서 Book클래스의 클래스 속성을 정의하는 예이다. Book 클래스는 BookLoan 클래스와는 다르게  상속구조를 사용한다. 즉, Book 클래스에서 PaperBook과 EBook 클래스가 상속된다. 각각의 클래스는 각각의 특징에 맞게 속성들을 정의하고, 특별히 Book 클래스에서는 클래스 수준의 book_list 속성이 정의되어, 생성된 Book 클래스와 PaperBook/EBook 클래스의 인스턴스들을 book_list 속성에 저장한다. 

 

예상 코드

class Book:
    _book_list = []

    def __init__(self, book_id, title, author, isbn):
        self.id = book_id
        self.title = title
        self.author = author
        self.ISBN = isbn

        Book._book_list.append(self)

    @classmethod
    def display_list(cls):
        print("=" * 110)
        print("전체 도서 목록".center(85))
        print("=" * 110)
        print(f"{'구분':6} {'ID':<4} {'제목':20} {'저자':10} {'ISBN':15} {'추가정보'}")
        print("-" * 100)

        for book in Book._book_list:
            # Book 타입별로 추가정보 생성
            if isinstance(book, PaperBook):
                extra_info = f"서가:{book.shelf_location:<6} 대출가능:{book.available_copies}권"
                book_type = "PBook"
            elif isinstance(book, EBook):
                extra_info = f"형식:{book.file_format:<6} 크기:{book.file_size_mb:<5}MB 동시:{book.max_simultaneous_users}명"
                book_type = "EBook"

            print(f"{book_type:8} {book.id:<4} {book.title:20} {book.author:10} {book.ISBN:15} {extra_info}")

        print("=" * 110)


class PaperBook(Book):
    def __init__(self, book_id, title, author, isbn, shelf_location, available_copies):
        super().__init__(book_id, title, author, isbn)
        self.shelf_location = shelf_location
        self.available_copies = available_copies

    @classmethod
    def display_list(cls):
        print("=" * 85)
        print("일반도서 목록".center(85))
        print("=" * 85)
        print(f"{'ID':<4} {'제목':22} {'저자':10} {'서가':10} {'대출가능권수'}")
        print("-" * 70)

        for book in Book._book_list:
            if isinstance(book, PaperBook):
                print(
                    f"{book.id:<4} "
                    f"{book.title:22} "
                    f"{book.author:10} "
                    f"{book.shelf_location:10} "
                    f"{book.available_copies:<10}"
                )

        print("=" * 85)


class EBook(Book):
    def __init__(self, book_id, title, author, isbn, file_format, file_size_mb, max_simultaneous_users):
        super().__init__(book_id, title, author, isbn)
        self.file_format = file_format
        self.file_size_mb = file_size_mb
        self.max_simultaneous_users = max_simultaneous_users

    @classmethod
    def display_list(cls):
        print()
        print("=" * 85)
        print("전자책 목록".center(85))
        print("=" * 85)
        print(f"{'ID':<4} {'제목':22} {'저자':10} {'형식':8} {'크기(MB)':10} {'동시대출'}")
        print("-" * 75)

        for book in Book._book_list:
            if isinstance(book, EBook):
                print(
                    f"{book.id:<4} "
                    f"{book.title:22} "
                    f"{book.author:10} "
                    f"{book.file_format:8} "
                    f"{book.file_size_mb:<10} "
                    f"{book.max_simultaneous_users:<10}"
                )

        print("=" * 85)


# 객체 생성
book1 = PaperBook(1, "OOP", "홍길동", "978-89-1234", "A-3-2", 3)
book2 = EBook(2, "Python Basic", "김철수", "978-89-5678", "PDF", 12.5, 10)
book3 = PaperBook(3, "Data Structure", "이영희", "978-89-1111", "B-1-4", 2)
book4 = EBook(4, "Algorithm", "박민수", "978-89-2222", "EPUB", 8.3, 5)

Book.display_list()
PaperBook.display_list()
EBook.display_list()
  • 2라인 클래스 수준의 속성 생성:  클래스 수준의 속성으로 _book_list를 리스트 타입으로 정의하였다.
  • 10라인 리스트에 인스턴스 대입: 클래스 인스턴스 생성시, 즉 생성자 __init__()에서 self 인스턴스가 만들어지면 _book_list.append(self)로 __book_list에 해당 인스턴스를 append 한다. 
  • 13라인부터 Book 클래스의 _book_list의 인스턴스를 도서목록으로 출력하는 메소드 
    • 14 ~18라인: 목록의 title을 출력한다. 
    • 20라인 for book in Book._book_list:
      • _book_list의 항목 하나하나를 book 변수에 대입하여, 대입된 인스턴스 type(PaperBook or EBook)에 맞게 추가정보를 생성한다. (다형성 작동)
    • 20~27라인: _book_list에는 PaperBook, EBook 모든 인스턴스가 들어가 있다. 해서 Book의 공통정보인 id, 제목, 저자, ISBN은 공통으로 출력하고, PaperBook과 EBook 고유의 정보는 추가정보로 묶어서 출력한다. 20-27라인 코드가 Book 타입별로 추가정보를 하나의 변수로 생성하는 부분이다. 
    • 29 라인: 실제 도서정보 한건을 출력한다. 
  • 40~58라인: book_list 속성에서 일반도서(PapaerBook) 정보만 출력한다.
    • 49라인:  if isinstance(book, PaperBook):
      • isisnacne() 함수는 첫번째 매개변수가 두번째 매개변수 type인지를 확인해준다. 즉, book 변수에 대입된 인스턴스가 PaperBook 클래스 타입인지를 확인해여 맞으면 True 아니면 False를 리턴한다. 
  • 69~88라인: book_list 속성에서 전자도서(EBook) 정보만 출력한다.
    • 78라인: 49 라인과 동일하게 작동한다. 

 

실습. 키오스크의 메 도메인에서 상속관계 클래스 찾기

 

아래 클래스 다이어그램은 키오스크 도메인에서 MenuItem의 상속구조를 보여준다. 

 

 

위 상속구조에 클래스 수준의 속성인 menu_item_list를 정의하고 도서관 시스템의 예상 클래스 다이어그램과 예상 코드를 참조하여 아래 요구사항에서 상속관계의 클래스를 도출하여 클래스 다이어그램을 그리고, 파이썬 코드로 구현하시오. 

 

제출1. 클래스 다이어그램

제출 2. 파이썬 코드

  • 1. 제출 1을 파이썬으로 구현한 클래스 코드
    • menu_item_list를 정의하고, __init__ ()에서 만들어진 인스턴스를 리스트에 append 해준다. 
  • 2. MenuItem/Coffee/Desser 클래스에서 display_list( ) 메소드를 정의한다.
    • MunuItem 클래스에서는 menu_item_list의 항목들을 모두 목록으로 출력한다.
    • Coffee 클래스의 display_list ()에서는 _menu_item_list에서 Coffee 클래스의 인스턴스만 출력한다.
    • Dessert 클래스의 display_list()에서는 _menu_item_list에서 Dessert 클래스의 인스턴스만 출력한다. 
  • 3. (위) 1번, 2번에서 구현한 클래스에 대해 클래스 인스턴스들을 각각(Coffee, Dessert) 3개씩 생성하고, 전체메뉴, 커피메뉴, 디저트 메뉴를 출력하는 코드를 작성한다.
    • 출력예시
==========================================================================================
                                         전체 메뉴 목록                                         
==========================================================================================
Type     ID   Name                 Price      Available Stock   More Info
------------------------------------------------------------------------------------------
Coffee   1    Americano            3000       10                카페인:120 mg 온도:hot
Coffee   2    Latte                4000       5                 카페인:90  mg 온도:iced
Coffee   3    Mocha                4500       7                 카페인:150 mg 온도:hot
Dessert  4    Cheese Cake          4500       4                 칼로리:350 kcal 보관:냉장
Dessert  5    Macaron              2500       8                 칼로리:180 kcal 보관:실온
Dessert  6    Tiramisu             5000       3                 칼로리:420 kcal 보관:냉장
==========================================================================================

==========================================================================================
                               커피 메뉴 목록                               
==========================================================================================
ID   Name                 Price      Available Stock   caffeine(mg) Temperature
------------------------------------------------------------------------------------------
1    Americano            3000       10                120          hot     
2    Latte                4000       5                 90           iced    
3    Mocha                4500       7                 150          hot     
==========================================================================================

==========================================================================================
                                        디저트 메뉴 목록                                         
==========================================================================================
ID   Name                 Price      Available Stock   Calorie(kcal)  Storage Type
------------------------------------------------------------------------------------------
4    Cheese Cake          4500       4                 350            냉장      
5    Macaron              2500       8                 180            실온      
6    Tiramisu             5000       3                 420            냉장      
==========================================================================================

 

 

클래스 다이어그램 예시

코드 예시

더보기
class MenuItem:
    _menu_item_list = []

    def __init__(self, item_id, name, price, available_stock):
        self._id = item_id
        self._name = name
        self._price = price
        self._available_stock = available_stock

        MenuItem._menu_item_list.append(self)

    def order(self, quantity):
        if quantity <= 0:
            print("주문 수량은 1개 이상이어야 합니다.")
            return

        if self._available_stock >= quantity:
            self._available_stock -= quantity
            print(f"{self._name} {quantity}개 주문 완료")
        else:
            print(f"{self._name} 재고 부족")

    @classmethod
    def display_list(cls):
        print("=" * 90)
        print("전체 메뉴 목록".center(90))
        print("=" * 90)
        print(f"{'Type':8} {'ID':<4} {'Name':20} {'Price':10} {'Available Stock':17} {'More Info'}")
        print("-" * 90)

        for item in MenuItem._menu_item_list:
            if isinstance(item, Coffee):
            #     extra_info = f"카페인:{item.__caffeine_amount:<4}mg 온도:{'hot' if item.__temperature_type == 1 else 'iced'}"
                item_type = "Coffee"
            elif isinstance(item, Dessert):
            #     storage_dict = {1: "실온", 2: "냉장", 3: "냉동"}
            #     extra_info = f"칼로리:{item.__calories_kcal:<4}kcal 보관:{storage_dict.get(item.__storage_type, '알수없음')}"
                item_type = "Dessert"
            else:
            #     extra_info = ""
                item_type = "Menu"

            # print(f"{item_type:8} {item.id:<4} {item.name:20} {item.price:<10} {item.available_stock:<17} {extra_info}")
            print(f"{item_type:8} {item._id:<4} {item._name:20} {item._price:<10} {item._available_stock:<17} ")

        print("=" * 90)


class Coffee(MenuItem):
    def __init__(self, item_id, name, price, available_stock, caffeine_amount, temperature_type):
        super().__init__(item_id, name, price, available_stock)
        self.__caffeine_amount = caffeine_amount
        self.__temperature_type = temperature_type

    @classmethod
    def display_list(cls):
        print()
        print("=" * 90)
        print("커피 메뉴 목록".center(70))
        print("=" * 90)
        print(f"{'ID':<4} {'Name':20} {'Price':10} {'Available Stock':17} {'caffeine(mg)':12} {'Temperature'}")
        print("-" * 90)

        for item in MenuItem._menu_item_list:
            if isinstance(item, Coffee):
                temp_text = "hot" if item.__temperature_type == 1 else "iced"
                print(
                    f"{item._id:<4} "
                    f"{item._name:20} "
                    f"{item._price:<10} "
                    f"{item._available_stock:<17} "
                    f"{item.__caffeine_amount:<12} "
                    f"{temp_text:<8}"
                )

        print("=" * 90)


class Dessert(MenuItem):
    def __init__(self, item_id, name, price, available_stock, calories_kcal, storage_type):
        super().__init__(item_id, name, price, available_stock)
        self.__calories_kcal = calories_kcal
        self.__storage_type = storage_type

    @classmethod
    def display_list(cls):
        print()
        print("=" * 90)
        print("디저트 메뉴 목록".center(90))
        print("=" * 90)
        print(f"{'ID':<4} {'Name':20} {'Price':10} {'Available Stock':17} {'Calorie(kcal)':14} {'Storage Type'}")
        print("-" * 90)

        storage_dict = {1: "실온", 2: "냉장", 3: "냉동"}

        for item in MenuItem._menu_item_list:
            if isinstance(item, Dessert):
                print(
                    f"{item._id:<4} "
                    f"{item._name:20} "
                    f"{item._price:<10} "
                    f"{item._available_stock:<17} "
                    f"{item.__calories_kcal:<14} "
                    f"{storage_dict.get(item.__storage_type, '알수없음'):<8}"
                )

        print("=" * 90)


# 객체 생성 - Coffee 3개
menu1 = Coffee(1, "Americano", 3000, 10, 120, 1)
menu2 = Coffee(2, "Latte", 4000, 5, 90, 2)
menu3 = Coffee(3, "Mocha", 4500, 7, 150, 1)

# 객체 생성 - Dessert 3개
menu4 = Dessert(4, "Cheese Cake", 4500, 4, 350, 2)
menu5 = Dessert(5, "Macaron", 2500, 8, 180, 1)
menu6 = Dessert(6, "Tiramisu", 5000, 3, 420, 2)

# 출력
MenuItem.display_list()
Coffee.display_list()
Dessert.display_list()

+ Recent posts