2-1. 키오스크 코드에서 중복 코드 찾아 함수로 정의하고 배열의 포인터 넘기기

문제 설명

아래 코드는 콘솔 키오스크 코드의 예시로 menu_item의 등록/수정/삭제/조회 기능이 구현되어 있다. 이 중 메뉴 수정, 삭제 기능은 배열을 순회하면서 사용자가 입력한 menu_id에 해당하는 메뉴의 위치, 즉 인덱스를 찾아야 한다. 이번 문제에서는 메뉴 배열을 함수의 인자로 전달하고, 배열을 순회하여 특정 menu_id를 가진 메뉴의 인덱스를 반환하는 함수를 구현한다.

 

목표

  • 배열명이 함수에 전달될 때 포인터처럼 동작함을 이해한다.
  • 구조체 배열을 함수의 인자로 전달할 수 있다.
  • 배열을 순회하여 원하는 데이터를 찾을 수 있다.
  • 공통 기능을 함수로 정의하고, 필요한 곳에서 호출하여 재상요 할 수 있음을 이해한다. 
  • 검색 함수를 modify_menu_item()과 delete_menu_item()에서 재사용할 수 있다.

요구사항

 

1. 다음 함수를 구현하시오.

int find_menu_index(MenuItem *menu_list, int count, int menu_id);
  • 입력 매개변수
    • menuItem* menu_list : 순회할 메뉴리스트의 주소를 받는다. 
    • int count: 등록된 메뉴 개수 
    • int menu_id: 찾고자 하는 메뉴 id
  • find_menu_index() 함수의 기능은 다음과 같다.
    • menu_list 배열을 처음부터 count 까지 순회한다.
    • 배열 요소의 menu_id가 찾고자 하는 menu_id와 같으면 해당 인덱스를 반환한다.
    • 찾지 못하면 -1을 반환한다.

2. modify_menu_item() 함수에서 직접 반복문으로 메뉴를 찾지 말고, find_menu_index() 함수를 사용하시오.

3. delete_menu_item() 함수에서도 직접 반복문으로 메뉴를 찾지 말고, find_menu_index() 함수를 사용하시오.

 

개념 확인 질문

  1. find_menu_index() 함수에서 MenuItem *menu_list는 무엇을 의미하는가?
  2. coffee_menu_list를 함수에 전달하면 배열 전체가 복사되는가, 배열의 시작 주소가 전달되는가?
  3. 메뉴를 찾지 못했을 때 -1을 반환하는 이유는 무엇인가?
  4. find_menu_index() 함수를 만들면 modify와 delete 코드가 왜 더 좋아지는가?

 

2-2. 키오스크 코드에서  배열 요소 삭제 함수 구현 (Call-by-reference)

 

문제설명

메뉴를 삭제할 경우 삭제된 위치 뒤의 요소들을 한 칸씩 앞으로 이동(shift)해야 하며, 메뉴 개수(count)도 감소해야 한다. 이번 문제에서는 배열과 count를 함수의 인자로 전달하여 커피 메뉴나 디저트 메뉴에서 삭제할때 사용할 함수를 구현한다.

 

목표

  • 구조체 배열을 함수의 인자로 전달할 수 있다.
  • 배열 요소를 shift하여 삭제 기능을 구현할 수 있다.
  • count 값을 함수 내부에서 변경하기 위해 Call-by-reference 방식(포인터 전달)을 사용할 수 있다.

요구사항

 

1. 다음 함수를 구현하시오.

void delete_menu(MenuItem *menu_list, int *p_menu_count, int delete_index);
 
  • 입력매개변수
    • MenuItem* menu_list: 삭제하고자 하는 메뉴리스트 배열의 포인터
    • int *p_menu_counter: 삭제하고자 하는 메뉴리스트의 현재 등록된 메뉴항목 개수를 가리키는 포인터
    • int delete_index: 삭제하고자 하는 요소의 index
  • delete_menu() 함수의 동작은 다음과 같다.
    • delete_index 위치의 메뉴를 삭제한다.
    • 삭제된 위치 뒤의 요소들을 한 칸씩 앞으로 이동한다.
    • 메뉴 개수(count)를 1 감소시킨다.

2. delete_menu_item() 함수에서 직접 shift 코드를 작성하지 말고 delete_menu() 함수를 호출하시오.

3. 메뉴 개수 감소가 실제 원본 변수에 반영되도록 구현하시오. [단, 코드에서는 coffee_count, menu_count가 전역변수로 정의되어 있으나, 본 문제에서는 local 변수라 가정하고 call-by-reference를 수행한다.] 

 

개념확인 질문 

  • MenuItem *menu_list는 무엇을 의미하는가?
  • coffee_menu_list를 함수에 전달하면 실제로 무엇이 전달되는가?
  • menu_count를 int * menu_count 형태로 전달한 이유는 무엇인가?
  • 아래 코드에서 괄호의 위치에 따라 어떻게 다른지 설명하시오. 
(*menu_count)--;
*(menu_count--);

 

[수정 전 코드] 아래 코드를 사용하여 2-1, 2-2를 수행하시오. 

[콘솔키오스크] 과제 2단계. 메뉴 관리 기능 구현 [5/7] - 결과 예시 코드에서 수정/삭제의 편의를 위해 초기 데이타를 각각 5건씩 추가한 코드이다. 

#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;

MenuItem coffee_menu_list[MAX_MENU] = {
    {100, "Americano", 3000, 1},
    {101, "Latte", 4000, 1},
    {102, "Mocha", 4500, 1},
    {103, "VanillaLatte", 4800, 0},
    {104, "Espresso", 2500, 1}
};

MenuItem dessert_menu_list[MAX_MENU] = {
    {200, "Cake", 5000, 1},
    {201, "Cookie", 2000, 1},
    {202, "Waffle", 4500, 0},
    {203, "Macaron", 3000, 1},
    {204, "CheeseCake", 5500, 1}
};

int coffee_count = 5;
int dessert_count = 5;

int next_coffee_id = 105;
int next_dessert_id = 205;

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;
}

 

예상 코드

더보기
더보기
#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;

MenuItem coffee_menu_list[MAX_MENU] = {
    {100, "Americano", 3000, 1},
    {101, "Latte", 4000, 1},
    {102, "Mocha", 4500, 1},
    {103, "VanillaLatte", 4800, 0},
    {104, "Espresso", 2500, 1}
};

MenuItem dessert_menu_list[MAX_MENU] = {
    {200, "Cake", 5000, 1},
    {201, "Cookie", 2000, 1},
    {202, "Waffle", 4500, 0},
    {203, "Macaron", 3000, 1},
    {204, "CheeseCake", 5500, 1}
};

int coffee_count = 5;
int dessert_count = 5;

int next_coffee_id = 105;
int next_dessert_id = 205;

int find_menu_index(MenuItem *menu_list, int count, int menu_id)
{
    for (int i = 0; i < count; i++)
    {
        if (menu_list[i].menu_id == menu_id)
        {
            return i;
        }
    }

    return -1;
}

void delete_menu(MenuItem *menu_list, int *p_menu_count, int delete_index)
{
    for (int i = delete_index; i < (*p_menu_count) - 1; i++)
    {
        menu_list[i] = menu_list[i + 1];  // i+1번째 요소를 i번째 요소로 shift
    }

    (*p_menu_count)--;
}

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) {

        the_index = find_menu_index(coffee_menu_list, coffee_count, menu_id);

        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)
    {
        the_index = find_menu_index(dessert_menu_list, dessert_count, menu_id);
      
        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) {
        the_index = find_menu_index(coffee_menu_list, coffee_count, menu_id);
       
        if (the_index == -1) {
            printf("해당 메뉴를 찾을 수 없습니다.\n");
            return;
        }

        delete_menu(coffee_menu_list, &coffee_count,the_index);
    }
    else if (type == 2) {
        the_index = find_menu_index(dessert_menu_list, dessert_count, menu_id);

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

        delete_menu(dessert_menu_list, &dessert_count,the_index);
    }

    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;
}

 

 

 

+ Recent posts