1. 결과를 위한 주요 개념 정리

1.1 데이타 구조 설계에서 구조체로의 구현

설계에서의 자료구조

자료구조 멤버이름 멤버 자료형 설명
메뉴 정보: MenuItem




메뉴번호(menu_id) int serical 3자리
[참고] menu_id는 마지막 menu_id + 1로 증가하며, 삭제된 ID는 재사용하지 않는다.
  메뉴명(name) 문자배열[20]   
  가격(price): int int  
  판매상태(status) - int  1. 판매중, 2. 품절 

코드에서의 구조체 선언 - 구조체 멤버를 정의하고 typedef로  MenuItem을 재정의한다. 

typedef struct menu_item{
    int menu_id;
    char name[20];
    int price;
    int status;
} MenuItem;

 

1.2. 구조체 배열을 활용하여 커피 메뉴, 디저트 메뉴 정의

구조체를 요소로 하는 배열을 정의한다. 

  • 키오스크에서 관리하는 메뉴 종류는 커피, 디저트 두가지 종류이다
    • 따라서 커피 리스트(coffee_menu_list), 디저트 리스트(dessert_menu_list) 2개의 배열을 정의해야 한다. 
  • 요구사항에서 메뉴의 최대개수는 10개로 정의 했으므로, 배열의 개수는 10으로 정의한다. 
    • 배열의 최대개수는 조정의 여지가 있으므로 상수로 정의하고 추후 변경을 용이하게한다. 
    • 추후 define문의 10만 변경하면 코드 전체의 변경이 쉬워진다.   
#define MAX_MENU 10

typedef struct menu_item{
    int menu_id;
    char name[20];
    int price;
    int status;
} MenuItem;

MenuItem coffee_menu_list[MAX_MENU];
MenuItem dessert_menu_list[MAX_MENU];

 

1.3. 메뉴 등록 / 조회 / 변경 기능을 실제 동작하도록 구현

 

1.3.메뉴 등록 순서 설계 및 코드

 

메뉴 등록 실행 순서

1. 사용자에게 메뉴구분 (1. 커피, 2. 디저트)을 입력받는다. 
2. 사용자가 메뉴구분을 입력한다. 
2.1 메뉴 구분에 따라 (커피라면) 현재 입력된 커피 개수 몇개인지 확인한다. 
       -> 입력된 커피 개수를 저장할 변수가 필요하다. -> int coffee_count = 0;
2.2  menu_id를 생성한다.
      -> [요구사항] coffee 메뉴의 menu_id는 100번 부터 시작하고,
                           dessert menu의 menu_id는 200번부터 시작한다. 
      -> 커피와 디저트 개수가 추가될 때마다 1씩 증가시키는 next_menu_id가
           커피와 디저트에 각각 필요하다.  
      ->  변수를 정의한다. 
            int next_coffee_id = 100;   
            int next_dessert_id = 200;
2.3 메뉴 정보의 이름, 가격, 설명을 입력받는다.   (2.2와 2.3 은 순서 조정가능)
      -> 현재 이용해야 할 배열의 해당 번째 요소에 구조체 멤버에 입력 받는다. 
            : 예.  coffee_menu_list[coffee_count].name 에 매뉴명을 입력받는다. 
                  scanf("%s", coffee_menu_list[coffee_count].name);  
      -> 해당 배열에  메뉴 아이디를 저장한다. 
              coffee_menu_list[coffee_count].menu_id = next_coffee_id; 
2.4. 저장이 완료되었다.
      -> coffee_count와 next_coffee_id 를 1씩 증가하여 다음 메뉴 입력에서 사용한다.  

메뉴 등록 코드

#include <stdio.h>
#include "menu_item.h"
#define MAX_MENU 10

typedef struct menu_item {
    int menu_id;
    char name[20];
    int price;
    int status;
} MenuItem;

MenuItem coffee_menu_list[MAX_MENU];
MenuItem dessert_menu_list[MAX_MENU];

int coffee_count = 0;
int dessert_count = 0;

int next_coffee_id = 100;
int next_dessert_id = 200;


void register_menu_item(void)
{
    int type;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);

    if (type == 1 && coffee_count < MAX_MENU)
    {
        coffee_menu_list[coffee_count].menu_id = next_coffee_id++;
        coffee_menu_list[coffee_count].status = 1;

        printf("메뉴명: ");
        scanf(" %s", coffee_menu_list[coffee_count].name);

        printf("가격: ");
        scanf("%d", &coffee_menu_list[coffee_count].price);

        coffee_count++;
    }
    else if (type == 2 && dessert_count < MAX_MENU)
    {
        dessert_menu_list[dessert_count].menu_id = next_dessert_id++;
        dessert_menu_list[dessert_count].status = 1;

        printf("메뉴명: ");
        scanf(" %s", dessert_menu_list[dessert_count].name);

        printf("가격: ");
        scanf("%d", &dessert_menu_list[dessert_count].price);

        dessert_count++;
    }
    else
    {
        printf("등록 실패\n");
    }
}

 

1.3.3 메뉴 수정 순서 설계 및 코드 

 

메뉴 수정 순서 

  1. 메뉴 구분을 입력받는다. 
  2. 구분에 맞는 메뉴 리스트를 출력한다. 
  3. 메뉴 id를 선택하게 한다. - 선택한 id에 대한 배열의 인덱스를 찾는다. 이 인덱스로 해당 배열의 값을 수정해야 한다
  4. 선택한 id의 수정값을 입력 받는다. 
  5. 입력한 값으로 수정한다. 
  6. 수정 완료

메뉴 수정 코드

void modify_menu_item(void)
{
    int type;
    int menu_id;
    int the_index = -1;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);

    if (type == 1)
        retrieve_coffee_menu_item();
    else if (type == 2)
        retrieve_dessert_menu_item();
    else {
        printf("잘못된 메뉴구분입니다.\n");
        return;
    }

    printf("수정할 메뉴 ID: ");
    scanf("%d", &menu_id);

    if (type == 1)     {
        for (int i = 0; i < coffee_count; i++) {
            if (coffee_menu_list[i].menu_id == menu_id) {
                the_index = i;
                break;
            }
        }

        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }
        
        printf("새 메뉴명: ");
        scanf(" %s", coffee_menu_list[the_index].name);

        printf("새 가격: ");
        scanf("%d", &coffee_menu_list[the_index].price);

        printf("판매상태 (1. 판매중, 0. 품절): ");
        scanf("%d", &coffee_menu_list[the_index].status);

        printf("메뉴 수정 완료\n");
    }
    else if (type == 2)
    {
        for (int i = 0; i < dessert_count; i++)
        {
            if (dessert_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }
        
        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }

        printf("새 메뉴명: ");
        scanf(" %s", dessert_menu_list[the_index].name);

        printf("새 가격: ");
        scanf("%d", &dessert_menu_list[the_index].price);

        printf("판매상태 (1. 판매중, 0. 품절): ");
        scanf("%d", &dessert_menu_list[the_index].status);
    }
    printf("메뉴 수정 완료\n");
}

 

 1.3.4 메뉴 삭제 순서 설계 및 코드 

 

메뉴 삭제 순서 

  1. 메뉴 구분을 입력받는다. 
  2. 구분에 맞는 메뉴 리스트를 출력한다. 
  3. 메뉴 id를 선택하게 한다. - 선택한 id에 대한 배열의 인덱스를 찾는다. 이 인덱스로 해당 배열을 삭제해야 한다.  
  4. 선택한 id에 대한 배열을 삭제하기 위해
    1. 다음 배열의 항목을 해당 배열로 shift 시킨다. 
    2. 마지막 항목까지 하나씩 shift 시킨다. 
    3. 현재 메뉴 카운드를 1 감소한다 .
  5. 삭제 완료

메뉴 삭제 코드

void delete_menu_item(void)
{
    int type;
    int menu_id;
    int the_index = -1;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);
    if (type == 1)
        retrieve_coffee_menu_item();
    else if (type == 2)
        retrieve_dessert_menu_item();
    else {
        printf("잘못된 메뉴구분입니다.\n");
        return;
    }
    
    printf("삭제할 메뉴 ID: ");
    scanf("%d", &menu_id);

    if (type == 1)
    {
        for (int i = 0; i < coffee_count; i++)
        {
            if (coffee_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }

        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }

        for (int i = the_index; i < coffee_count - 1; i++)
        {
            coffee_menu_list[i] = coffee_menu_list[i + 1];
        }

        coffee_count--;       
    }
    else if (type == 2)
    {
        for (int i = 0; i < dessert_count; i++)
        {
            if (dessert_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }

        if (the_index == -1)
        {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }
        
        for (int i = the_index; i < dessert_count - 1; i++)
        {
            dessert_menu_list[i] = dessert_menu_list[i + 1];
        }

        dessert_count--;
    }

    printf("메뉴 삭제 완료\n");
}

 

2. 전체 코드

선택1. 통합 파일 : main.c

더보기
#include <stdio.h>

#define MAX_MENU 10

typedef struct menu_item {
    int menu_id;
    char name[20];
    int price;
    int status;
} MenuItem;

MenuItem coffee_menu_list[MAX_MENU];
MenuItem dessert_menu_list[MAX_MENU];

int coffee_count = 0;
int dessert_count = 0;

int next_coffee_id = 100;
int next_dessert_id = 200;

void retrieve_coffee_menu_item(void){
    printf("\n\n====================[Coffee]======================\n");
    printf("%-4s %-20s %7s   %-10s\n", "No", "Name", "Price", "Status");
    printf("----------------------------------------------------\n");
    for (int i = 0; i < coffee_count; i++) {
        printf("%-4d %-20s %7d   %-10s\n",
               coffee_menu_list[i].menu_id,
               coffee_menu_list[i].name,
               coffee_menu_list[i].price,
               (coffee_menu_list[i].status) ? "AVAILABLE" : "SOLD OUT");
    }
    printf("\n==================================================\n");
}

void retrieve_dessert_menu_item(void){
    printf("\n\n====================[Dessert]=====================\n");
    printf("%-4s %-20s %7s   %-10s\n", "No", "Name", "Price", "Status");
    printf("----------------------------------------------------\n");

    for (int i = 0; i < dessert_count; i++) {
        printf("%-4d %-20s %7d   %-10s\n",
               dessert_menu_list[i].menu_id,
               dessert_menu_list[i].name,
               dessert_menu_list[i].price,
               (dessert_menu_list[i].status) ? "AVAILABLE" : "SOLD OUT");
    }

    printf("\n==================================================\n");
}


void retrieve_menu_item(void){
    retrieve_coffee_menu_item();
    retrieve_dessert_menu_item();
}

void register_menu_item(void)
{
    int type;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);

    if (type == 1 && coffee_count < MAX_MENU)
    {
        coffee_menu_list[coffee_count].menu_id = next_coffee_id++;
        coffee_menu_list[coffee_count].status = 1;

        printf("메뉴명: ");
        scanf(" %s", coffee_menu_list[coffee_count].name);

        printf("가격: ");
        scanf("%d", &coffee_menu_list[coffee_count].price);

        coffee_count++;
    }
    else if (type == 2 && dessert_count < MAX_MENU) 
    {
        dessert_menu_list[dessert_count].menu_id = next_dessert_id++;
        dessert_menu_list[dessert_count].status = 1;

        printf("메뉴명: ");
        scanf(" %s", dessert_menu_list[dessert_count].name);

        printf("가격: ");
        scanf("%d", &dessert_menu_list[dessert_count].price);

        dessert_count++;
    }
    else
    {
        printf("등록 실패\n");
    }
}

void modify_menu_item(void)
{
    int type;
    int menu_id;
    int the_index = -1;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);

    if (type == 1)
        retrieve_coffee_menu_item();
    else if (type == 2)
        retrieve_dessert_menu_item();
    else {
        printf("잘못된 메뉴구분입니다.\n");
        return;
    }

    printf("수정할 메뉴 ID: ");
    scanf("%d", &menu_id);

    if (type == 1)     {
        for (int i = 0; i < coffee_count; i++) {
            if (coffee_menu_list[i].menu_id == menu_id) {
                the_index = i;
                break;
            }
        }

        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }
        
        printf("새 메뉴명: ");
        scanf(" %s", coffee_menu_list[the_index].name);

        printf("새 가격: ");
        scanf("%d", &coffee_menu_list[the_index].price);

        printf("판매상태 (1. 판매중, 0. 품절): ");
        scanf("%d", &coffee_menu_list[the_index].status);

        printf("메뉴 수정 완료\n");
    }
    else if (type == 2)
    {
        for (int i = 0; i < dessert_count; i++)
        {
            if (dessert_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }
        
        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }

        printf("새 메뉴명: ");
        scanf(" %s", dessert_menu_list[the_index].name);

        printf("새 가격: ");
        scanf("%d", &dessert_menu_list[the_index].price);

        printf("판매상태 (1. 판매중, 0. 품절): ");
        scanf("%d", &dessert_menu_list[the_index].status);
    }
    printf("메뉴 수정 완료\n");
}

void delete_menu_item(void)
{
    int type;
    int menu_id;
    int the_index = -1;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);
    if (type == 1)
        retrieve_coffee_menu_item();
    else if (type == 2)
        retrieve_dessert_menu_item();
    else {
        printf("잘못된 메뉴구분입니다.\n");
        return;
    }
    
    printf("삭제할 메뉴 ID: ");
    scanf("%d", &menu_id);

    if (type == 1)
    {
        for (int i = 0; i < coffee_count; i++)
        {
            if (coffee_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }

        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }

        for (int i = the_index; i < coffee_count - 1; i++)
        {
            coffee_menu_list[i] = coffee_menu_list[i + 1];
        }

        coffee_count--;       
    }
    else if (type == 2)
    {
        for (int i = 0; i < dessert_count; i++)
        {
            if (dessert_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }

        if (the_index == -1)
        {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }
        
        for (int i = the_index; i < dessert_count - 1; i++)
        {
            dessert_menu_list[i] = dessert_menu_list[i + 1];
        }

        dessert_count--;
    }

    printf("메뉴 삭제 완료\n");
}

void order(void)
{
    printf("[주문하기 기능 호출]\n");
}

void search_order(void)
{
    printf("[주문조회 기능 호출]\n");
}

void print_main_menu(void)
{
    printf("=========================================\n");
    printf("           SSU 카페 키오스크\n");
    printf("=========================================\n");
    printf("메뉴관리(관리자용)     주문관리(고객용)\n");
    printf("11. 메뉴 등록         21. 주문하기\n");
    printf("12. 메뉴 변경         22. 주문조회\n");
    printf("13. 메뉴 삭제\n");
    printf("14. 메뉴 조회\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_menu_item();
                break;

            case 12:
                modify_menu_item();
                break;

            case 13:
                delete_menu_item();
                break;

            case 14:
                retrieve_menu_item();
                break;

            case 21:
                order();
                break;

            case 22:
                search_order();
                break;

            default:
                printf("잘못된 입력\n");
        }

        printf("\n");
    }
}
 
int main(void)
{
    run();
    
    return 0;
}

 

선택2. 분할 파일: main.c,  kiosk_ui.c, kiosk_ui.h, menu_item.c, menu_item.h

더보기

main.c

#include "kiosk_ui.h"
 
int main(void)
{
    run();
    
    return 0;
}

 

kiosk_ui.h 

#ifndef KIOSK_UI_H
#define KIOSK_UI_H
 
void run(void);
 
#endif

 

kiosk_ui.c

#include <stdio.h>
#include "kiosk_ui.h"
#include "menu_item.h"

void order(void)
{
    printf("[주문하기 기능 호출]\n");
}

void search_order(void)
{
    printf("[주문조회 기능 호출]\n");
}

void print_main_menu(void)
{
    printf("=========================================\n");
    printf("           SSU 카페 키오스크\n");
    printf("=========================================\n");
    printf("메뉴관리(관리자용)     주문관리(고객용)\n");
    printf("11. 메뉴 등록         21. 주문하기\n");
    printf("12. 메뉴 변경         22. 주문조회\n");
    printf("13. 메뉴 삭제\n");
    printf("14. 메뉴 조회\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_menu_item();
                break;

            case 12:
                modify_menu_item();
                break;

            case 13:
                delete_menu_item();
                break;

            case 14:
                retrieve_menu_item();
                break;

            case 21:
                order();
                break;

            case 22:
                search_order();
                break;

            default:
                printf("잘못된 입력\n");
        }

        printf("\n");
    }
}

 

menu_item.h

#ifndef MENU_ITEM_H
#define MENU_ITEM_H

void register_menu_item(void);
void modify_menu_item(void);
void delete_menu_item(void);
void retrieve_menu_item(void);

#endif

 

menu_item.c

#include <stdio.h>
#include "menu_item.h"

#define MAX_MENU 10

typedef struct menu_item {
    int menu_id;
    char name[20];
    int price;
    int status;
} MenuItem;

MenuItem coffee_menu_list[MAX_MENU];
MenuItem dessert_menu_list[MAX_MENU];

int coffee_count = 0;
int dessert_count = 0;

int next_coffee_id = 100;
int next_dessert_id = 200;

void retrieve_coffee_menu_item(void){
    printf("\n\n====================[Coffee]======================\n");
    printf("%-4s %-20s %7s   %-10s\n", "No", "Name", "Price", "Status");
    printf("----------------------------------------------------\n");
    for (int i = 0; i < coffee_count; i++) {
        printf("%-4d %-20s %7d   %-10s\n",
               coffee_menu_list[i].menu_id,
               coffee_menu_list[i].name,
               coffee_menu_list[i].price,
               (coffee_menu_list[i].status) ? "AVAILABLE" : "SOLD OUT");
    }
    printf("\n==================================================\n");
}

void retrieve_dessert_menu_item(void){
    printf("\n\n====================[Dessert]=====================\n");
    printf("%-4s %-20s %7s   %-10s\n", "No", "Name", "Price", "Status");
    printf("----------------------------------------------------\n");

    for (int i = 0; i < dessert_count; i++) {
        printf("%-4d %-20s %7d   %-10s\n",
               dessert_menu_list[i].menu_id,
               dessert_menu_list[i].name,
               dessert_menu_list[i].price,
               (dessert_menu_list[i].status) ? "AVAILABLE" : "SOLD OUT");
    }

    printf("\n==================================================\n");
}


void retrieve_menu_item(void){
    retrieve_coffee_menu_item();
    retrieve_dessert_menu_item();
}

void register_menu_item(void)
{
    int type;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);

    if (type == 1 && coffee_count < MAX_MENU)
    {
        coffee_menu_list[coffee_count].menu_id = next_coffee_id++;
        coffee_menu_list[coffee_count].status = 1;

        printf("메뉴명: ");
        scanf(" %s", coffee_menu_list[coffee_count].name);

        printf("가격: ");
        scanf("%d", &coffee_menu_list[coffee_count].price);

        coffee_count++;
    }
    else if (type == 2 && dessert_count < MAX_MENU) 
    {
        dessert_menu_list[dessert_count].menu_id = next_dessert_id++;
        dessert_menu_list[dessert_count].status = 1;

        printf("메뉴명: ");
        scanf(" %s", dessert_menu_list[dessert_count].name);

        printf("가격: ");
        scanf("%d", &dessert_menu_list[dessert_count].price);

        dessert_count++;
    }
    else
    {
        printf("등록 실패\n");
    }
}

void modify_menu_item(void)
{
    int type;
    int menu_id;
    int the_index = -1;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);

    if (type == 1)
        retrieve_coffee_menu_item();
    else if (type == 2)
        retrieve_dessert_menu_item();
    else {
        printf("잘못된 메뉴구분입니다.\n");
        return;
    }

    printf("수정할 메뉴 ID: ");
    scanf("%d", &menu_id);

    if (type == 1)     {
        for (int i = 0; i < coffee_count; i++) {
            if (coffee_menu_list[i].menu_id == menu_id) {
                the_index = i;
                break;
            }
        }

        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }
        
        printf("새 메뉴명: ");
        scanf(" %s", coffee_menu_list[the_index].name);

        printf("새 가격: ");
        scanf("%d", &coffee_menu_list[the_index].price);

        printf("판매상태 (1. 판매중, 0. 품절): ");
        scanf("%d", &coffee_menu_list[the_index].status);

        printf("메뉴 수정 완료\n");
    }
    else if (type == 2)
    {
        for (int i = 0; i < dessert_count; i++)
        {
            if (dessert_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }
        
        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }

        printf("새 메뉴명: ");
        scanf(" %s", dessert_menu_list[the_index].name);

        printf("새 가격: ");
        scanf("%d", &dessert_menu_list[the_index].price);

        printf("판매상태 (1. 판매중, 0. 품절): ");
        scanf("%d", &dessert_menu_list[the_index].status);
    }
    printf("메뉴 수정 완료\n");
}

void delete_menu_item(void)
{
    int type;
    int menu_id;
    int the_index = -1;

    printf("메뉴구분 (1. 커피, 2. 디저트): ");
    scanf("%d", &type);
    if (type == 1)
        retrieve_coffee_menu_item();
    else if (type == 2)
        retrieve_dessert_menu_item();
    else {
        printf("잘못된 메뉴구분입니다.\n");
        return;
    }
    
    printf("삭제할 메뉴 ID: ");
    scanf("%d", &menu_id);

    if (type == 1)
    {
        for (int i = 0; i < coffee_count; i++)
        {
            if (coffee_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }

        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }

        for (int i = the_index; i < coffee_count - 1; i++)
        {
            coffee_menu_list[i] = coffee_menu_list[i + 1];
        }

        coffee_count--;       
    }
    else if (type == 2)
    {
        for (int i = 0; i < dessert_count; i++)
        {
            if (dessert_menu_list[i].menu_id == menu_id)
            {
                the_index = i;
                break;
            }
        }

        if (the_index == -1)
        {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }
        
        for (int i = the_index; i < dessert_count - 1; i++)
        {
            dessert_menu_list[i] = dessert_menu_list[i + 1];
        }

        dessert_count--;
    }

    printf("메뉴 삭제 완료\n");
}

 

1-1. 배열 전달과 포인터

문제설명

배열을 함수의 인자로 전달할 때 실제로 어떤 형태로 전달되는지 확인하는 문제입니다.


목표

  • 배열명이 함수 호출 시 포인터처럼 전달된다는 점을 이해한다.
  • 배열 매개변수가 실제로는 포인터라는 점을 이해한다.

요구사항

아래 코드의 빈칸을 완성하시오.

#include <stdio.h>

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

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

    print_array(nums, 3);

    return 0;
}
 

 

예상 출력

10 20 30
 

 

예상 코드

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

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

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

    print_array(nums, 3);

    return 0;
}
 
 

1-2. Call-by-value

문제설명

값 전달(Call-by-value)의 특징을 이해하는 문제입니다.


목표

  • 함수 호출 시 값이 복사된다는 점을 이해한다.
  • 함수 내부 수정이 원본 변수에 영향을 주지 않는다는 점을 이해한다.

요구사항

아래 코드의 실행 결과를 예상하고 왜 그런 결과가 나왔는지를 설명하시오. 

#include <stdio.h>

void change(int num)
{
    num = 100;
}

int main(void)
{
    int value = 10;

    change(value);

    printf("%d\n", value);

    return 0;
}
 

예상 답안

더보기
더보기

실행결과

10
 

-> 함수 호출시 main()에서 value의 값만 change()로 num 매개변수에 복사되어 전달되기 때문이다. 

 

1-3. Call-by-reference 

문제설명

포인터를 이용하여 함수 밖 변수의 값을 수정한다.

 

목표

  • 주소 전달의 의미를 이해한다.
  • 포인터를 통해 원본 데이터를 수정할 수 있음을 이해한다.

요구사항

빈칸을 완성하여 value 값이 100으로 변경되도록 작성하시오.

 
#include <stdio.h>

void change( __________ )
{
    *num = 100;
}

int main(void)
{
    int value = 10;

    change( __________ );

    printf("%d\n", value);

    return 0;
}
 

예상 출력

100
 

 

예상코드

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

void change(int *num)
{
    *num = 100;
}

int main(void)
{
    int value = 10;

    change(&value);

    printf("%d\n", value);

    return 0;
}

 

1-4. const 포인터

 

문제설명

포인터와 const의 의미를 구분하는 문제입니다.

 

목표

  • const 위치에 따라 의미가 달라짐을 이해한다.
  • “값 변경 금지”와 “주소 변경 금지”를 구분한다.

요구사항

다음 코드 중 컴파일 오류가 발생하는 줄을 고르고  각 오류의 이유를 설명하시오. 

int num1 = 10;
int num2 = 20;

const int *ptr1 = &num1;
int * const ptr2 = &num1;

① *ptr1 = 30;
② ptr1 = &num2;

③ *ptr2 = 40;
④ ptr2 = &num2;
 

 

 

예상 답안

더보기
더보기

①: ptr1이 가리키는 값이 상수이므로 수정 불가능

④: ptr2 값 자체가 상수이므로 다른 주소를 저장할 수 없음

 

 

[카페키오스크] 과제 1 단계. 신규메뉴 등록 설계/구현 과정 이해 를 참조하여 아래 과제를 수행하시오. 

 

1. 카페 키오스크 시스템에서 "메뉴 수정" 기능의 시퀀스 다이어그램과 이를 통해 정제된 클래스 다이어그램을 작성하시오. 

2. 1번에서 작성된 설계를 기반으로 "메뉴 수정" 기능을 구현하시오. 


1. 카페키오스크요구사항

OO 카페 키오스크 시스템은 고객이 카페 메뉴를 빠르고 편리하게 주문할 수 있도록 지원하는 시스템이다. 이 시스템은 카페에서 판매하는 메뉴 정보를 기본 데이터로 관리하며, 이를 기반으로 메뉴 조회, 메뉴 선택, 주문 생성, 결제 및 주문 내역 저장 기능을 제공한다.
카페에서 판매하는 메뉴는 공통적으로 시스템에서 사용하는 메뉴의 고유 식별자(Menu ID), 메뉴명, 가격, 메뉴 설명, 판매 상태(판매중, 품절) 정보를 관리해야 한다. 메뉴는 종류에 따라 커피류(CoffeeMenu)와 디저트류(DessertMenu)로 구분된다. 커피류 메뉴는 추가적으로 원두 종류(bean type), HOT 제공 가능 여부, ICE 제공 가능 여부 정보를 관리해야 한다. 디저트류 메뉴는 추가적으로 칼로리(calories)와 알레르기 정보(allergy information)를 관리해야 한다. 메뉴의 고유식별자(Menu ID)는 메뉴의 등록 순서번호를 사용하며 중간에 삭제가 되어도 다음에 등록된 번호는 최종 번호 +1로 생성한다.
고객은 키오스크 화면에서 메뉴 목록을 조회할 수 있어야 하며, 각 메뉴에 대해 메뉴명, 가격, 판매 상태가 표시되어야 한다. 품절 상태의 메뉴는 화면에 표시되더라도 선택이 불가능해야 한다.
고객이 주문을 진행하기 위해 메뉴를 선택하면, 시스템은 해당 메뉴의 상세 정보를 보여주고 사용자는 수량을 선택할 수 있어야 한다. 선택한 메뉴는 주문 항목으로 추가되며, 사용자는 여러 개의 메뉴를 하나의 주문에 포함시킬 수 있어야 한다. 고객이 주문을 확정하면 시스템은 주문을 생성하고 관련 정보를 저장해야 한다. 저장해야 할 정보에는 주문번호(고유 식별자), 주문 항목 목록(메뉴 ID, 메뉴명, 수량, 항목별 금액), 총 주문 금액, 주문 생성 시간(주문 시각), 주문 상태(: 주문접수)가 포함된다.
주문 생성 후 고객은 결제를 진행해야 한다. 결제는 공통적으로 결제번호, 결제금액, 결제시간, 결제상태(결제완료, 결제실패), 결제방식을 관리해야 한다. 결제 방식은 신용카드(CreditCardPayment)와 카카오페이(KakaoPayPayment)를 지원한다. 신용카드 결제는 카드사(card company)와 카드번호(card number)를 관리해야 하며, 카카오페이 결제는 카카오 계정 ID를 관리해야 한다. 하나의 주문은 하나의 결제와 연결되며, 결제가 완료되면 주문 상태는 “결제완료” 변경된다.
주문이 정상적으로 생성되고 결제가 완료되면 키오스크는 사용자에게 주문번호와 함께 주문 내역(메뉴명, 수량, 총액, 결제방식)을 화면에 표시해야 한다.

 

2. 카페키오스크 유스케이스 다이어그램

 

 

3. 메뉴 등록 유스케이스 명세서

Use case Diagarm Use case Description

 

[제출 1]  메뉴수정 시퀀스 다이어그램

//TODO

[제출 2]  수정기능으로 보완된 메뉴관리 클래스 다이어그램 

//TODO

[제출3] 메뉴 수정 기능이 구현된 코드

//TODO

 

1. 문제 설명

1단계에서 구현한 키오스크 프로그램은 메뉴 화면(UI)과 기능 호출 구조만 존재하는 상태이다. 이번 단계에서는 실제로 카페 메뉴 데이터를 저장하고 관리하는 기능을 구현한다. 

 

2. 목표

  • 1단계에서 분석된 데이타 정보중 메뉴 정보구조체로 설계한다. 
  • 구조체 배열을 활용하여 커피 메뉴, 디저트 메뉴를 관리할 수 있다
  • 메뉴 등록 / 조회 / 변경 기능을 실제 동작하도록 구현할 수 있다
  • UI → 기능 → 데이터 흐름을 연결할 수 있다

 

3. 요구사항

3.1 데이터 구조 설계

3.1.1 MenuItem 구조체 정의

다음의 1단계에서 도출된 메뉴 정보를 구조체로 정의하시오. 단) typedef로 구조체 type의 별명(alias)을 MenuItem으로 정의하시오. 

자료구조 멤버이름 멤버 자료형 설명
메뉴 정보: MenuItem




메뉴번호(menu_id) int serical 3자리
[참고] menu_id는 마지막 menu_id + 1로 증가하며, 삭제된 ID는 재사용하지 않는다.
  메뉴명(name) 문자배열[20]   
  가격(price): int int  
  판매상태(status) - int  1. 판매중, 2. 품절 

Hint

더보기
더보기
더보기
typedef struct{
        int menu_id;
        char name[20];
        int price;
        int status;
} MenuItem;

 

3.1.2 MenuItem type의 coffee list와 dessert list를 배열로 정의하시오. 

  • 각 list는 최대 10개까지 저장 가능하도록 (배열 size 10) 정의 한다
  • coffee list와 dessert list는 전역/로컬 auto/로컬static 중 무엇으로 정의해야 할까?
  • 현재 등록된 메뉴 개수를 관리하는 변수를 선언하여 필요시 사용한다. 
  • coffee 메뉴의 menu_id는 100번 부터 시작하고, dessert menu의 menu_id는 200번부터 시작한다. 

예:

#define MAX_MENU 10

MenuItem coffee_list[MAX_MENU];
int coffee_menu_count = 0;
 

3.2 메뉴관리 기능 구현

과제 1단계에서 만든 함수들을 실제 기능으로 구현한다. 즉, 1단계의 run() 함수에서 기존 switch문을 유지하고, 호출하는 내부 함수만 실제 구현으로 교체한다. 

 

3.2.1 메뉴 등록 기능 -  register_menu_item()

 

요구사항:

  • 커피메뉴인지, 디저트 메뉴인지 선택한다.
  • 메뉴명, 가격을 입력받는다
  • menu_id는 자동 증가로 설정한다
  • status는 기본값 “판매중(1)”으로 설정한다
  • 배열에 저장한다

출력 예:

메뉴구분 (1. 커피, 2. 디저트): 1
메뉴명 입력: 아메리카노
가격 입력: 3000
[등록 완료]
 

 

3.2.2  메뉴 조회 기능 - retrieve_menu_item()

 

요구사항:

  • 모든 메뉴를 출력한다
  • 출력 형식:
====================[Coffee]======================
No   Name                  Price    Status
==================================================
101  Americano               3000   AVAILABLE
102  Cafe Latte              4000   AVAILABLE
103  Cappuccino              4000   SOLD OUT
104  Vanilla Latte           4500   AVAILABLE

====================[Dessert]=====================
No   Name                  Price    Status
==================================================
201  Cheesecake              5000   AVAILABLE
202  Chocolate Cake          5000   AVAILABLE
203  Tiramisu                5500   SOLD OUT
204  Macaron                 2000   AVAILABLE
205  Croissant               3000   AVAILABLE

==================================================
 

3.2.3 메뉴 변경 기능 - modify_menu_item()

 

요구사항:

  • 전체 메뉴를 보여준다.
  • 수정할 메뉴 번호 입력
  • 수정 항목 선택:  1. 메뉴명, 2. 가격, 3. 판매상태
  • 해당 항목을 수정

출력 예:

====================[Coffee]======================
No   Name                  Price    Status
==================================================
101  Americano               3000   AVAILABLE
102  Cafe Latte              4000   AVAILABLE
103  Cappuccino              4000   SOLD OUT
104  Vanilla Latte           4500   AVAILABLE

====================[Dessert]=====================
No   Name                  Price    Status
==================================================
201  Cheesecake              5000   AVAILABLE
202  Chocolate Cake          5000   AVAILABLE
203  Tiramisu                5500   SOLD OUT
204  Macaron                 2000   AVAILABLE
205  Croissant               3000   AVAILABLE

==================================================

수정할 메뉴 번호 입력: 101
수정할 항목(1. 메뉴명, 2. 가격, 3. Status): 2
변경할 가격: 3500
==> 아래와 같이 수정되었습니다. 
No: 101
Name: Americano
Price: 3500
Status: AVAILABLE

 

3.2.4 메뉴 삭제 기능 - delete_menu_item()


요구사항:

  • 전체 메뉴를 보여준다.
  • 삭제 할 메뉴 번호 입력
  • 해당 항목을 삭제
  • 해당 항목 삭제후 배열을 재정렬 한다. - 즉 coffee_list[3]의 메뉴가 삭제되었으면 coffee_list[4] 메뉴가 coffee_list[3]으로 이동하고 이를 반복한다. 

출력 예:

====================[Coffee]======================
No   Name                  Price    Status
==================================================
101  Americano               3000   AVAILABLE
102  Cafe Latte              4000   AVAILABLE
103  Cappuccino              4000   SOLD OUT
104  Vanilla Latte           4500   AVAILABLE

====================[Dessert]=====================
No   Name                  Price    Status
==================================================
201  Cheesecake              5000   AVAILABLE
202  Chocolate Cake          5000   AVAILABLE
203  Tiramisu                5500   SOLD OUT
204  Macaron                 2000   AVAILABLE
205  Croissant               3000   AVAILABLE

==================================================

삭제할 메뉴 번호 입력: 204
==> 삭제되었습니다. 

====================[Coffee]======================
No   Name                  Price    Status
==================================================
101  Americano               3000   AVAILABLE
102  Cafe Latte              4000   AVAILABLE
103  Cappuccino              4000   SOLD OUT
104  Vanilla Latte           4500   AVAILABLE

====================[Dessert]=====================
No   Name                  Price    Status
==================================================
201  Cheesecake              5000   AVAILABLE
202  Chocolate Cake          5000   AVAILABLE
203  Tiramisu                5500   SOLD OUT
205  Croissant               3000   AVAILABLE

==================================================

 

 

 

3.3 파일 분리 (선택)

  • 분할 파일: main.c,  kiosk_ui.c, kiosk_ui.h, menu_item.c, menu_item.h

 

4. 제출 형식 

  • 선택1. 통합 파일 : main.c
  • 선택2. 분할 파일: main.c,  kiosk_ui.c, kiosk_ui.h, menu_item.c, menu_item.h

1. 카페키오스크요구사항

OO 카페 키오스크 시스템은 고객이 카페 메뉴를 빠르고 편리하게 주문할 수 있도록 지원하는 시스템이다. 이 시스템은 카페에서 판매하는 메뉴 정보를 기본 데이터로 관리하며, 이를 기반으로 메뉴 조회, 메뉴 선택, 주문 생성, 결제 및 주문 내역 저장 기능을 제공한다.
카페에서 판매하는 메뉴는 공통적으로 시스템에서 사용하는 메뉴의 고유 식별자(Menu ID), 메뉴명, 가격, 메뉴 설명, 판매 상태(판매중, 품절) 정보를 관리해야 한다. 메뉴는 종류에 따라 커피류(CoffeeMenu)와 디저트류(DessertMenu)로 구분된다. 커피류 메뉴는 추가적으로 원두 종류(bean type), HOT 제공 가능 여부, ICE 제공 가능 여부 정보를 관리해야 한다. 디저트류 메뉴는 추가적으로 칼로리(calories)와 알레르기 정보(allergy information)를 관리해야 한다. 메뉴의 고유식별자(Menu ID)는 메뉴의 등록 순서번호를 사용하며 중간에 삭제가 되어도 다음에 등록된 번호는 최종 번호 +1로 생성한다.
고객은 키오스크 화면에서 메뉴 목록을 조회할 수 있어야 하며, 각 메뉴에 대해 메뉴명, 가격, 판매 상태가 표시되어야 한다. 품절 상태의 메뉴는 화면에 표시되더라도 선택이 불가능해야 한다.
고객이 주문을 진행하기 위해 메뉴를 선택하면, 시스템은 해당 메뉴의 상세 정보를 보여주고 사용자는 수량을 선택할 수 있어야 한다. 선택한 메뉴는 주문 항목으로 추가되며, 사용자는 여러 개의 메뉴를 하나의 주문에 포함시킬 수 있어야 한다. 고객이 주문을 확정하면 시스템은 주문을 생성하고 관련 정보를 저장해야 한다. 저장해야 할 정보에는 주문번호(고유 식별자), 주문 항목 목록(메뉴 ID, 메뉴명, 수량, 항목별 금액), 총 주문 금액, 주문 생성 시간(주문 시각), 주문 상태(: 주문접수)가 포함된다.
주문 생성 후 고객은 결제를 진행해야 한다. 결제는 공통적으로 결제번호, 결제금액, 결제시간, 결제상태(결제완료, 결제실패), 결제방식을 관리해야 한다. 결제 방식은 신용카드(CreditCardPayment)와 카카오페이(KakaoPayPayment)를 지원한다. 신용카드 결제는 카드사(card company)와 카드번호(card number)를 관리해야 하며, 카카오페이 결제는 카카오 계정 ID를 관리해야 한다. 하나의 주문은 하나의 결제와 연결되며, 결제가 완료되면 주문 상태는 “결제완료” 변경된다.
주문이 정상적으로 생성되고 결제가 완료되면 키오스크는 사용자에게 주문번호와 함께 주문 내역(메뉴명, 수량, 총액, 결제방식)을 화면에 표시해야 한다.

 

2. 카페키오스크 유스케이스 다이어그램

 

 

3. 메뉴 등록 유스케이스 명세서

Use case Diagarm Use case Description



 

Use case Description Brief Sequence Diagram

 

4. 메뉴관리 클래스 다이어그램

 

 

5. 메뉴등록 시퀀스 다이어그램

 

 

6. 클래스 다이어그램 정제

7. 메뉴등록 구현

class MenuItem:
    def __init__(self, menu_id, menu_type, name, price, description, status):
        self.__menu_id = menu_id
        self.__menu_type = menu_type
        self.__name = name
        self.__price = price
        self.__description = description
        self.__status = status

    # Getter (읽기 전용)
    @property
    def menu_id(self):
        return self.__menu_id

    @property
    def menu_type(self):
        return self.__menu_type

    @property
    def name(self):
        return self.__name

    @property
    def price(self):
        return self.__price

    @property
    def description(self):
        return self.__description

    @property
    def status(self):
        return self.__status


class MenuRepository:
    def __init__(self):
        self.__menu_list = []
        self.__next_menu_id = 1

    def generate_menu_item_id(self):
        menu_id = self.__next_menu_id
        self.__next_menu_id += 1
        return menu_id

    def add_menu_item(self, menu_item):
        self.__menu_list.append(menu_item)

    def find_all(self):
        return self.__menu_list


class MenuController:
    def __init__(self):
        self.__menu_repository = MenuRepository()

    def check_mandatory_field(self, name, price, status):
        return all([name, price, status])  # all() 안에 하나라도 비어있으면 False, 아니면 True

    def register_menu_item(self, menu_type, name, price, description, status):
        menu_id = self.__menu_repository.generate_menu_item_id()

        menu_item = MenuItem(
            menu_id,
            menu_type,
            name,
            int(price),
            description,
            status
        )

        self.__menu_repository.add_menu_item(menu_item)

    def retrieve_menu_list(self):
        menu_items = self.__menu_repository.find_all()

        result = []
        for item in menu_items:
            result.append({
                "menu_id": item.menu_id,
                "menu_type": item.menu_type,
                "name": item.name,
                "price": item.price,
                "description": item.description,
                "status": item.status
            })

        return result

class MainUI:
    def __init__(self):
        self.__menu_controller = MenuController()
        
    def run(self):
        while True:
            self.__print_main_menu()
            selected_menu = input("메뉴를 선택하세요: ")

            if selected_menu == "11":
                self.__select_register_menu()
            elif selected_menu == "12":
                self.__select_modify_menu()
            elif selected_menu == "13":
                self.__select_delete_menu()
            elif selected_menu == "14":
                self.__select_retrieve_menu()
            elif selected_menu == "21":
                self.__select_order()
            elif selected_menu == "0":
                print("프로그램 종료")
                break
            else:
                print("잘못된 입력")

    def __print_main_menu(self):
        print("\n============= 카페 키오스크 =============")
        print("메뉴관리(관리자)       주문관리(고객)")
        print("11. 메뉴 등록          21. 주문[TODO]")
        print("12. 메뉴 수정[TODO]")
        print("13. 메뉴 삭제[TODO]")
        print("14. 메뉴 조회")
        print("0. 종료")
        print("\n========================================")

    def __select_register_menu(self):
        print("\n[메뉴 등록]")
        print("1. Coffee")
        print("2. Dessert")

        menu_type_input = input("유형 선택: ")

        if menu_type_input == "1":
            menu_type = "Coffee"
        elif menu_type_input == "2":
            menu_type = "Dessert"
        else:
            print("잘못된 유형")
            return

        name = input("메뉴명: ")
        price = input("가격: ")
        description = input("설명: ")
        status = input("상태(1. 판매중, 2. 품절): ")

        if not self.__menu_controller.check_mandatory_field(name, price, status):
            print("누락된 정보를 입력하세요(필수정보:메뉴명, 가격, 상태)")
            return

        self.__menu_controller.register_menu_item(
            menu_type, name, price, description, status
        )

        print("등록 완료")

    def __select_retrieve_menu(self):
        print("\n[메뉴 조회]")

        menu_list = self.__menu_controller.retrieve_menu_list()

        if not menu_list:
            print("메뉴 없음")
            return

        print("=" * 60)
        print(f"{'ID':<5} {'유형':<10} {'이름':<10} {'가격':<8} {'상태':<8}")
        print("-" * 60)

        for m in menu_list:
            print(
                f"{m['menu_id']:<5} "
                f"{m['menu_type']:<10} "
                f"{m['name']:<10} "
                f"{m['price']:<8} "
                f"{m['status']:<8}"
            )

    def __select_modify_menu(self):
        print("[TODO] 메뉴정보 수정 선택")

    def __select_delete_menu(self):
        print("[TODO] 메뉴정보 삭제 선택")

    def __select_order(self):
        print("[TODO] 주문 선택")


if __name__ == "__main__":
    ui = MainUI()
    ui.run()

 

 

[참고] UML 다이어그램 draw.io 버전 

콘솔키오스크.drawio
0.12MB

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

1. 요구사항

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

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

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

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

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

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

 

2. 기능분석

2.1. 기능 리스트

1. 카페 메뉴 관리

 - 카페 메뉴 조회
- 카페 메뉴 등록
- 카페 메뉴 수정
- 카페 메뉴 삭제

2. 주문관리

- 주문하기
    -  메뉴 조회 ->  메뉴 선택 (반복하기) -> 카트에 넣기 (반복하기) -> 선택완료
- 결제하기
   -  결제방법 선택 (1. 신용카드, 2. 카카오페이) -> 결제처리
- 주문정보(+결제정보) 출력

 

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


1. 메뉴 정보

- 메뉴번호(menu_id)
- 메뉴명(name)
- 가격(price)
- 판매상태(status) - 판매중/품절


2. 주문 정보

2.1 주문 항목
- 메뉴명, 수량

2.2. 주문정보
- 주문 번호(order_id)
- 주문 항목 리스트 (2.1의 주문항목의 리스트)
- 총 금액

2.3 결제정보
- 주문번호
- 결제방식
- 결제금액
- 결제상태 

 

3. 간략 설계

 

3.1 화면 메뉴 설계

=========================================
           SSS 카페 키오스크
=========================================
메뉴관리(관리자용)     주문관리
11. 메뉴 등록         21. 주문하기
12. 메뉴 변경         22. 주문조회
13. 메뉴 삭제
14. 메뉴 조회
0. 종료
=========================================
메뉴 번호를 입력하세요 (0: 종료):

 

 

3.2 모듈(파일) 설계 - (지속적 상세화 진행예정)

 

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

선택 1.  통합버전 main.c

 #include <stdio.h>
 
void register_menu_item(void)
{
    printf("[TODO] 메뉴 등록 기능 호출!\n");
}
 
void modify_menu_item(void)
{
    printf("[TODO] 메뉴 변경 기능 호출!\n");
}
 
void delete_menu_item(void)
{
    printf("[TODO] 메뉴 삭제 기능 호출!\n");
}

void retrieve_menu_item(void)
{
    printf("[TODO] 메뉴 조회 기능 호출!\n");
}
 
void order(void)
{
    printf("[주문하기 기능 호출]\n");
}
 
void search_order(void)
{
    printf("[주문조회 기능 호출]\n");
}
 
void print_main_menu(void)
{
    printf("=========================================\n");
    printf("           SSS 카페 키오스크\n");
    printf("=========================================\n");
    printf("메뉴관리(관리자용)     주문관리\n");
    printf("11. 메뉴 등록         21. 주문하기\n");
    printf("12. 메뉴 변경         22. 주문조회\n");
    printf("13. 메뉴 삭제\n");
    printf("14. 메뉴 조회\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_menu_item();
                break;
 
            case 12:
                modify_menu_item();
                break;
 
            case 13:
                retrieve_menu_item();
                break;
 
            case 21:
                order();
                break;
 
            case 22:
                search_order();
                break;
 
            default:
                printf("잘못된 메뉴 번호입니다.\n");
        }
 
        printf("\n");
    }
}
 
int main(void)
{
    run();
    return 0;
}

 

 

 

선택 2. 분할 버전

 

- 파일 분할 개념

  • kiosk_ui.c 파일은 함수의 기능을 구현하고, kiosk_ui.h 파일은 외부(main.c)에서 호출할 수 있는 함수를 보여준다.
  • kiosk_ui.h에 오픈된 함수의 내구 구현을 kiosk_ui.c에 작성한다. 
  • main.c에서 kiosk_ui의 함수를 호출하려면, kiosk_ui.h 파일을 include 한다. 
    • #include "kiosk_ui.h" 
  • 분할된 파일의 c 파일을 컴파일 한다.  
    • main.c 와 kiosk.c 파일을 각각 compile 하여 main.o, kiosk.o를 생성
    • link 단계에서 main.o와 kiosk.o를 합쳐 kiosk.exe 생성  
gcc main.c kiosk_ui.c -o kiosk

 

 

main.c

#include "kiosk_ui.h"

int main(void)
{
    run();
    
    return 0;
}

 

kiosk_ui.h

#ifndef KIOSK_UI_H
#define KIOSK_UI_H

void run(void);

#endif

 

kiosk_ui.c

#include <stdio.h>
#include "kiosk_ui.h"

void register_menu_item(void)
{
    printf("[TODO] 메뉴 등록 기능 호출!\n");
}
 
void modify_menu_item(void)
{
    printf("[TODO] 메뉴 변경 기능 호출!\n");
}
 
void delete_menu_item(void)
{
    printf("[TODO] 메뉴 삭제 기능 호출!\n");
}

void retrieve_menu_item(void)
{
    printf("[TODO] 메뉴 조회 기능 호출!\n");
}
 
void order(void)
{
    printf("[주문하기 기능 호출]\n");
}
 
void search_order(void)
{
    printf("[주문조회 기능 호출]\n");
}
 
void print_main_menu(void)
{
    printf("=========================================\n");
    printf("           SSS 카페 키오스크\n");
    printf("=========================================\n");
    printf("메뉴관리(관리자용)     주문관리\n");
    printf("11. 메뉴 등록         21. 주문하기\n");
    printf("12. 메뉴 변경         22. 주문조회\n");
    printf("13. 메뉴 삭제\n");
    printf("14. 메뉴 조회\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_menu_item();
                break;

            case 12:
                modify_menu_item();
                break;

            case 13:
                retrieve_menu_item();
                break;

            case 21:
                order();
                break;

            case 22:
                search_order();
                break;

            default:
                printf("잘못된 메뉴 번호입니다.\n");
        }

        printf("\n");
    }
}
 



3-1 상품 주문 관리 구조체 만들기

문제설명

상품과 주문 정보를 구조체로 설계하고, 구조체 배열과 포인터를 활용하여 주문 정보를 출력하는 프로그램을 작성하시오.

 

목표

이 문제 하나로 다음 개념을 모두 확인한다:

  • 구조체 정의 및 초기화
  • 구조체 배열
  • 구조체 포인터
  • -> 연산자
  • 구조체 내부 포인터
  • typedef
  • 구조체 주소 개념

요구사항

 

1. 구조체 정의 - 다음 구조체를 정의하시오.

상품(product)
- name (문자열)
- price (정수)

주문(order)
- quantity (정수)
- product를 가리키는 포인터
  • typedef를 사용하여 Product, Order로 정의하시오.

2. 데이터 생성 - 다음 데이터를 생성하시오.

  • 상품 배열 2개
    • "Keyboard", 50000
    • "Mouse", 30000
  • 주문 배열 2개
    • 첫 번째 주문 → Keyboard, 수량 2
    • 두 번째 주문 → Mouse, 수량 3

3. 출력 - 다음 형식으로 출력하시오.

Product     Price  Qty Total Amount
========================================
Keyboard    50000    2 100000
Mouse       30000    3  90000
========================================
 

4. 포인터 활용 - 반드시 아래 방식 모두 사용

  • orders[i].product->name
  • (*orders[i].product).price

5. 주소 확인 - 다음을 출력하고 결과를 확인하시오.

&products[0]
&products[0].name
 

질문) 결과가 같은지 왜 그런지 설명하시오. 

 

출력예시

Product     Price  Qty Total Amount
========================================
Keyboard    50000    2 100000
Mouse       30000    3  90000
========================================
000000e6cbbffc20
000000e6cbbffc20
 

 

 

예상코드

더보기
#include <stdio.h>

typedef struct {
    char name[20];
    int price;
} Product;

typedef struct {
    int quantity;
    Product *product;
} Order;

int main(void)
{
    Product products[2] = {
        {"Keyboard", 50000},
        {"Mouse", 30000}
    };

    Order orders[2] = {
        {2, &products[0]},
        {3, &products[1]}
    };

    printf("%-10s %6s %4s %6s\n", "Product", "Price", "Qty", "Total Amount");
    printf("========================================\n");

    for(int i=0; i<2; i++) {
        int total = orders[i].quantity * (*orders[i].product).price;

        printf("%-10s %6d %4d %6d\n",
               orders[i].product->name,
               (*orders[i].product).price,
               orders[i].quantity,
               total);
    }
    printf("========================================\n");

    // 주소 확인
    printf("%p\n", &products[0]);
    printf("%p\n", &products[0].name);

    return 0;
}
 

2-1 구조체 정의 및 사용 (학생 정보)

문제설명

학생의 정보를 저장하는 구조체를 정의하고 기본 사용을 연습하는 문제이다.

 

목표

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

요구사항

  • struct student를 정의하시오
    • name[20] (문자열)
    • score (정수)
  • 변수 s1을 선언하고
    • 이름: "Kim"
    • 점수: 90
  • 값을 출력하시오
 

출력예시

Kim 90
 

 

예상코드

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

struct student {
    char name[20];
    int score;
};

int main(void) {
    struct student s1 = {"Kim", 90};
    printf("%s %d\n", s1.name, s1.score);
    return 0;
}
 

2-2 구조체 배열 (도서 목록)

문제설명

여러 개의 도서 정보를 구조체 배열로 관리하는 문제이다.

 

목표

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

요구사항

  • struct book 정의
    • title[20] (문자열)
    • price (정수)
  • 배열 2개 생성
    • "C언어", 20000
    • "자료구조", 25000
  • 반복문으로 출력
 

출력예시

C언어 20000
자료구조 25000

 

 

 

예상코드

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

struct book {
    char title[20];
    int price;
};

int main(void) {
    struct book arr[2] = {
        {"C언어", 20000},
        {"자료구조", 25000}
    };

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

    return 0;
}

 

 

2-3 구조체 포인터 (상품)

문제설명

구조체 포인터를 사용하여 값을 출력하는 문제이다.

 

목표

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

 

요구사항

  • struct product 정의
    • name, price
  • 변수 p1 = {"Laptop", 1000} 생성
  • 포인터 p가 p1을 가리키도록 설정
  • 아래 두 방식으로 출력
    • (*p).name
    • p->name
 

 

 출력예시

Laptop 1000
Laptop 1000
 
 
예상코드

 

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

struct product {
    char name[20];
    int price;
};

int main(void) {
    struct product p1 = {"Laptop", 1000};
    struct product *p = &p1;

    printf("%s %d\n", (*p).name, (*p).price);
    printf("%s %d\n", p->name, p->price);

    return 0;
}

 

2-4: 구조체 내부 포인터 (주문)

문제설명

구조체 안에 포인터를 포함하는 구조를 연습하는 문제이다.

 

목표

  • 구조체 내부 포인터 이해
  • 참조 관계 이해

요구사항

struct order {
    int quantity;
    struct product *item;
};
 
  • product 변수 생성 ("Mouse", 50)
  • order 생성 (수량 3)
  • 상품 이름과 가격 출력
 

출력예시

Mouse 50
 

 

예상코드

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

struct product {
    char name[20];
    int price;
};

struct order {
    int quantity;
    struct product *item;
};

int main(void) {
    struct product p = {"Mouse", 50};
    struct order o = {3, &p};

    printf("%s %d\n", o.item->name, o.item->price);

    return 0;
}

 

 

2-5 구조체 주소 확인

문제설명

구조체의 메모리 배치 특성을 확인하는 문제이다.

 

목표

  • 구조체 주소 이해

요구사항

struct student s = {"Lee", 80};

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

질문) 코드를 완성하여 실행 후 결과를 비교하시오

 

예상 답안

더보기
더보기

두 주소는 동일하다

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

 

코드예시

#include <stdio.h>

struct student {
    char name[20];
    int score;
};

int main(void)
{
    struct student s = {"Lee", 80};

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

    return 0;
}

 

 

 

2-6 typedef (회원)

문제설명

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

 

목표

  • typedef 이해

요구사항

  • 회원 구조체 정의 (name, age)
  • typedef로 Member로 선언
  • 변수 생성 후 출력
 

출력예시

Park 25
 

 

예상 코드

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

typedef struct {
    char name[20];
    int age;
} Member;

int main(void) {
    Member m = {"Park", 25};
    printf("%s %d\n", m.name, m.age);
    return 0;
}
 
 

+ Recent posts