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() 함수를 사용하시오.
개념 확인 질문
- find_menu_index() 함수에서 MenuItem *menu_list는 무엇을 의미하는가?
- coffee_menu_list를 함수에 전달하면 배열 전체가 복사되는가, 배열의 시작 주소가 전달되는가?
- 메뉴를 찾지 못했을 때 -1을 반환하는 이유는 무엇인가?
- 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;
}
'[1] 프로그래밍1 및 실습(C언어) > 11주차. 포인터와 함수' 카테고리의 다른 글
| [11주차][포인터와 함수] 1단계 연습문제 - 개념복습 (0) | 2026.05.08 |
|---|