-
2-1 재고량 관리 프로그램Computer Science/Boostcourse CS50 2021. 12. 24. 02:19728x90
네이버 부스트코스 대외활동을 진행하면서 만들어 봤던 첫번째 C언어 프로그램은 바로 구조체, 함수, 배열, 반복문, 조건문를 이용한 재고량 관리 프로그램입니다. 부족한 부분이 있겠지만, 나름대로 기능을 나누고 함수화하여 최대한 사용자 관점에서 가독성을 생각하며 구현해보았습니다.
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #define SIZE 30 typedef struct { int inventory, order, remain_inventory, price; double sales, TAX; char name[SIZE]; }PRODUCT; int cnt = 0; // 물품 종류 수 void product_input(PRODUCT* p); // 재고 관리 void product_init(PRODUCT* p); // 부가가치세, 남은 재고량, 매출액 계산 void product_search(PRODUCT* p); // 물품 검색(있는지 없는지만 확인하는 기능) void product_print(PRODUCT* p); // 주문건, 재고량, 매출액 출력 void delay_key(); // 메뉴 출력 전 딜레이 int main() { printf("----------------재고 관리 프로그램----------------\n"); PRODUCT p[SIZE]; int choice; while(1) { printf("\n-----------------------MENU-----------------------\n"); printf("1. 재고 관리\n"); printf("2. 물품 검색\n"); printf("3. 물품 정보\n"); printf("4. 프로그램 종료\n"); printf("--------------------------------------------------\n"); scanf("%d",&choice); switch(choice) { case 1: product_input(p); break; case 2: product_search(p); break; case 3: product_print(p); break; case 4: printf("프로그램을 종료합니다.\n"); exit(1); default: printf("잘못 입력하셨습니다. 다시 입력해주세요.\n"); break; } } return 0; } void product_input(PRODUCT* p) { while(1) { printf("물품명: "); scanf("%s",p[cnt].name); printf("재고량: "); scanf("%d",&p[cnt].inventory); printf("물품 가격: "); scanf("%d",&p[cnt].price); printf("주문건수: "); scanf("%d",&p[cnt].order); printf("--------------------------------------------------\n"); if(p[cnt].inventory<p[cnt].order) { // 재고량 초과에 대한 예외처리 printf("\n재고량을 초과하였습니다. 다시 입력해주세요.\n"); printf("--------------------------------------------------\n"); continue; } printf("\n주문이 완료되었습니다.\n"); delay_key(); product_init(p); cnt++; break; } } void product_init(PRODUCT* p) { p[cnt].TAX = (p[cnt].price)*0.1; // 부가가치세 p[cnt].remain_inventory = p[cnt].inventory - p[cnt].order; // 남은 재고량 p[cnt].sales = p[cnt].order*p[cnt].price + p[cnt].order*p[cnt].TAX; // 매출액(부가세포함) } void product_search(PRODUCT* p) { char name[SIZE]; int i; if(cnt == 0) { // cnt가 0이면 물품이 아예 없다는 뜻이므로 함수 종료 printf("현재 물품이 없습니다.\n"); delay_key(); return; } printf("찾고계신 물품명을 입력해주세요.\n"); scanf("%s",name); for(i = 0; i<=cnt; i++) { if(strcmp(p[i].name, name) == 0) { printf("\n\'%s\'은(는) 있습니다.\n",name); delay_key(); return; // 물품이 있다면 바로 함수 종료 } } printf("\n\'%s\'은(는) 없습니다.\n", name); delay_key(); } void product_print(PRODUCT* p) { char name[SIZE]; int i; printf("물품명: "); scanf("%s",name); for(i = 0; i<=cnt; i++) { if(strcmp(p[i].name, name) == 0) { printf("가격: %d\n",p[i].price); printf("\n주문건수: %d건\n", p[i].order); printf("기존 재고량: %d개\n", p[i].inventory); printf("남은 재고량: %d개\n", p[i].remain_inventory); printf("매출액(부가세포함): %.1lf\n", p[i].sales); delay_key(); return; } } } void delay_key() { printf("\n계속하려면 아무 키나 누르십시오.\n"); getch(); printf("--------------------------------------------------\n"); }
프로그램 만들어본 경험이 별로 없는거 치고는 코드가 긴거 같으면서도 짧아보입니다.. ㅎ
이제 기능에 대해 먼저 간략하게 말씀을 드리고 자세하게 살펴보겠습니다. (문법의 개념 설명은 생략하겠습니다.)
1. 재고량 관리
2. 물품 검색 (물품명을 입력했을 때, 해당 물품이 있는지 없는지 확인)
3. 물품 정보 (가격, 주문건수, 기존 재고량, 주문 후 재고량, 매출액(부가세포함))
4. 프로그램 종료
전에도 말씀드렸지만 프로그램의 스케일은 작아도 의미있는 프로그램을 구현하고자 이렇게 기능별로 나누었고,
각각의 기능을 함수로 다시 그룹핑시켜 구조체 배열을 이용해 물품 재고에 관한 정보를 저장해두는 방식입니다.
#include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #define SIZE 30 typedef struct { int inventory, order, remain_inventory, price; double sales, TAX; char name[SIZE]; }PRODUCT;
stdio.h은 표준 입출력 라이브러리, 나머지 헤더파일을 전처리한 이유를 각각 설명 드리자면
conio.h은 getch() 함수를 통해 기능을 실행했을 때 출력결과에 대한 딜레이를 주기 위한 것이며,
stdlib.h은 exit() 함수의 사용으로 프로그램 종료를 위해 포함시켰으며, string.h은 문자열 비교를 하기위해서 strcmp()를 사용해야 하므로 전처리 과정에 포함시켰습니다.
SIZE는 기호 상수로 상수에 이름을 명시해줌으로써 가독성을 생각해서 정의 해놓았습니다.
구조체 내에 선언되어 있는 변수는 이름에 나와있듯이 재고량, 주문건수, 남은 재고량, 물품 가격, 매출액, 부가가치세, 물품명으로 선언한 후 구조체를 정의하였습니다.
int cnt = 0; // 물품 종류 수 void product_input(PRODUCT* p); // 재고 관리 void product_init(PRODUCT* p); // 부가가치세, 남은 재고량, 매출액 계산 void product_search(PRODUCT* p); // 물품 검색(있는지 없는지만 확인하는 기능) void product_print(PRODUCT* p); // 주문건, 재고량, 매출액 출력 void delay_key(); // 메뉴 출력 전 딜레이 int main() { printf("----------------재고 관리 프로그램----------------\n"); PRODUCT p[SIZE]; int choice; while(1) { printf("\n-----------------------MENU-----------------------\n"); printf("1. 재고 관리\n"); printf("2. 물품 검색\n"); printf("3. 물품 정보\n"); printf("4. 프로그램 종료\n"); printf("--------------------------------------------------\n"); scanf("%d",&choice); switch(choice) { case 1: product_input(p); break; case 2: product_search(p); break; case 3: product_print(p); break; case 4: printf("프로그램을 종료합니다.\n"); exit(1); default: printf("잘못 입력하셨습니다. 다시 입력해주세요.\n"); break; } } return 0; }
여기서 cnt라는 변수를 전역 변수로 정의해놓았는데 그 이유는, main 함수뿐만 아니라 이외에 정의한 모든 사용자 정의 함수에서 물품 수에 대한 정보로 사용되기때문에 전역으로 정의하였습니다. 선언되어 있는 5개의 함수는 이후에 구체적으로 설명을 할 예정이니 우선 main 함수부터 살펴 보겠습니다.
main 함수 내 출력문들은 프로그램을 실행했을 때 보기 좋게 한다거나, 다른 코드들과 구분짓기 위하여 작성한 코드입니다. 위에서 정의한 SIZE 기호 상수를 이용해 구조체 배열의 크기를 정해 선언해놓았고, 메뉴에서 각 기능을 선택하기 위해 번호를 입력하는 변수인 choice를 선언하였습니다.
while문에는 어떤 기능들이 있는지 나타내는 출력문들과 번호에 따라 실행되는 코드들이 달라지게끔 switch문을 이용하였습니다. 이때 if/else문을 사용하여도 되겠지만 이도 마찬가지로 가독성을 조금 더 높이기 위해서 switch/case문을 사용했던 것 같습니다. default는 1~4번이 아닌 다른 문자나 번호를 입력했을 때를 방지하기 위해 예외처리에 대한 코드를 작성하였습니다.
그 전에 제가 프로그램들을 만들면서 느꼈던 것인데 말씀드리고 싶은 점은 어떤 프로그램을 만들때 위의 코드처럼main 함수 안에 코드가 길어지는 경우에는 최대한 함수화하여 관련된 코드들을 그룹핑해서 main 함수 내 코드를 줄이는 것이 사용자가 봤을 때도 보기에 편하다는 점과 이후에 만약 함수가 많아진다면 함수의 원형만 main 함수 위에 선언해놓고 함수가 정의된 부분은 main 함수 아래에 위치 해놓는다면 나중에 그룹원들과 프로젝트를 하거나 협업을 하는 데 있어서 더 효율적으로 관리할 수 있다는 것입니다.
이제 다시 이어나가 각 함수의 기능을 자세히 살펴보도록 하겠습니다.
void product_input(PRODUCT* p) { while(1) { printf("물품명: "); scanf("%s",p[cnt].name); printf("재고량: "); scanf("%d",&p[cnt].inventory); printf("물품 가격: "); scanf("%d",&p[cnt].price); printf("주문건수: "); scanf("%d",&p[cnt].order); printf("--------------------------------------------------\n"); if(p[cnt].inventory<p[cnt].order) { // 재고량 초과에 대한 예외처리 printf("\n재고량을 초과하였습니다. 다시 입력해주세요.\n"); printf("--------------------------------------------------\n"); continue; } printf("\n주문이 완료되었습니다.\n"); delay_key(); product_init(p); cnt++; break; } } void product_init(PRODUCT* p) { p[cnt].TAX = (p[cnt].price)*0.1; // 부가가치세 p[cnt].remain_inventory = p[cnt].inventory - p[cnt].order; // 남은 재고량 p[cnt].sales = p[cnt].order*p[cnt].price + p[cnt].order*p[cnt].TAX; // 매출액(부가세포함) }
product_input이라는 함수는 재고량을 관리하는 함수로, 위에 선언한 cnt 전역변수를 이용해 각 구조체 배열에 있는 공간에 접근하여 구조체 내 변수의 값들을 입력받도록 하였고, 재고량보다 주문건수가 더 크면 안되니 이에 대한 예외처리도 입력이 끝난 후 바로 아래에 하여 만약 재고량을 초과하는 경우 처음으로 돌아가 다시 입력받는 식으로 작성하였습니다.
입력을 제대로 받았다면 다시 확인하기 위해 약간의 delay를 주는 함수를 호출하였고, 이후 product_init이라는 함수를 통해 입력 받은 값들을 갖고 각 구조체의 부가가치세, 남은 재고량, 매출액을 이니셜라이즈 해주었습니다.
함수가 종료되면 물품이 하나 늘어났으니 cnt도 증가시켜주었고, while문을 탈출함과 동시에 product_input 함수도 종료를 하게됩니다.
delay_key 함수를 제외한 모든 함수의 매개변수는 PRODUCT* p로 되어 있는데 이것은 이전 main 함수에서 선언하였던 구조체 배열을 인자로 전달받고 그 배열을 함수 안에서 이용하기 위해 매개변수로 설정해놓은 것입니다.
product_input 함수를 작성하면서 아쉬웠던 점은 하나의 물품에 대해서 한번만 주문하는 것이 아니라
기존 재고량이 다 떨어질 때까지 주문할 수 있게끔 작성할 수 있었을텐데 하는 아쉬운 마음이 남아있습니다..ㅎ
void product_search(PRODUCT* p) { char name[SIZE]; int i; if(cnt == 0) { // cnt가 0이면 물품이 아예 없다는 뜻이므로 함수 종료 printf("현재 물품이 없습니다.\n"); delay_key(); return; } printf("찾고계신 물품명을 입력해주세요.\n"); scanf("%s",name); for(i = 0; i<=cnt; i++) { if(strcmp(p[i].name, name) == 0) { printf("\n\'%s\'은(는) 있습니다.\n",name); delay_key(); return; // 물품이 있다면 바로 함수 종료 } } printf("\n\'%s\'은(는) 없습니다.\n", name); delay_key(); }
product_search는 물품명을 입력했을 때 해당 물품이 있는지 없는지 검색하는 함수이며 이를 통해 다음에 나오게 될 물품 정보에 관한 함수에서 그 물품을 입력할지 말지 사용자가 결정할 수 있습니다.
기존에 저장되어 있던 구조체 배열의 물품명에 속하는지 확인하기 위해 char형 배열을 선언하여 입력받게 하였고, 만약에 cnt가 0이라면 물품이 아예 없으므로 함수가 바로 종료되게끔 작성하였습니다.
입력받은 물품명은 for문으로 strcmp(문자열 비교) 함수를 이용해 확인을 하는 것이며 만약 입력한 물품명이 구조체 배열에 저장되어 있다면 사용자에게 알린 후 그 상태에서 바로 함수는 종료되고, 만약 없다면 반복문에서 탈출하고 없다는 것을 알린 후 함수가 종료됩니다.
void product_print(PRODUCT* p) { char name[SIZE]; int i; printf("물품명: "); scanf("%s",name); for(i = 0; i<=cnt; i++) { if(strcmp(p[i].name, name) == 0) { printf("가격: %d\n",p[i].price); printf("\n주문건수: %d건\n", p[i].order); printf("기존 재고량: %d개\n", p[i].inventory); printf("남은 재고량: %d개\n", p[i].remain_inventory); printf("매출액(부가세포함): %.1lf\n", p[i].sales); delay_key(); return; } } } void delay_key() { printf("\n계속하려면 아무 키나 누르십시오.\n"); getch(); printf("--------------------------------------------------\n"); }
product_print는 이제까지 작성된 함수들을 바탕으로 가격, 주문건수, 기존 재고량, 남은 재고량, 매출액(부가세포함)이 연산된 결과들을 모두 출력해주는 함수이고, search 함수에서 본 것처럼 물품명을 입력하기 위하여 char형 배열 변수를 선언해서 입력했을 때 반복문으로 그 물품 정보가 저장된 구조체를 찾아서 출력하게 됩니다.
그리고 delay_key 함수가 거의 모든 함수에서 호출되었는데 이 함수를 작성한 이유는 delay가 없다면 함수를 호출하고 출력 결과를 볼때 바로 main 함수에 있는 메뉴가 출력 되기때문에 스크롤해서 봐야하는 불편함이 있었습니다.
이를 방지하기 위해 사용자가 정보를 확인하고 아무 키를 입력해야만 넘어갈 수 있게 getch() 함수를 통해 딜레이를 주었습니다.
실행 결과는 다음과 같습니다.
재고 관리
물품 검색
물품 정보
프로그램 종료 시
이를 끝으로 하여 저의 프로그램에 대한 설명이 끝이 났는데, 누군가에게 코드를 공유하고 리뷰, 피드백 하는 것은 처음이지만 이렇게 다시 한번 정리를 하고나니 저한테도 많은 도움이 된 것 같습니다.
728x90'Computer Science > Boostcourse CS50' 카테고리의 다른 글
3-1 학점 계산 프로그램 (0) 2021.12.24 3. 배열 (0) 2021.12.24 2-2 음식메뉴 소개 프로그램 (0) 2021.12.24 2. C언어 (0) 2021.12.24 1. 컴퓨팅 사고 (0) 2021.12.24