개요
파일 읽기/쓰기를 이용하여 DLL 자료구조를 이용하여 도서관리를 위한 자료를 편집할 수 있는 프로그램을 작성. ![]() ![]() |
목표
book_original.txt 100 1 고래 홍길동 1923 200 2 사자 이순신 1919 300 3 만세 유관순 1929 400 4 운동 김순자 2010 |
Code
bookManagement.c
#include"bookDLL.h"
int main(void)
{
BOOK_t* headNode = initailize_DLL();
BM_main(headNode);
free(headNode);
return 0;
}
bookDLL.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
#define U_SIZEOF (unsigned)sizeof
#define _LINE linePrint()
#define BUFFERSIZE 100
#define STRSIZE 20
const char* CAS[10][2] = { {"000","총류/컴퓨터"},{"100","철학"},{"200","종교"},{"300","사회과학"},{"400","자연과학"},
{"500","기술과학"},{"600","예술"},{"700","언어"},{"800","문학"},{"900","역사"} };
typedef struct BOOKLIST {
enum BOOKCATEGORY eCategory;
unsigned short usYear;
unsigned int uiCodeNum;
char strBookName[STRSIZE];
char strAuthor[STRSIZE];
struct BOOKLIST* prev;
struct BOOKLIST* next;
}BOOK_t;
typedef enum BOOKCATEGORY { GENERAL, PHIL = 100, RELIGION = 200, SOCIALSCI = 300, SCIENCE = 400, TECH = 500, ARTS = 600, LANGUAGE = 700, LITER = 800, HISTORY = 900 }KDC_e;
typedef enum CATEGORYARRSELELC { KDC, KOR }CAS_e;
enum SELMAINMENU { QUIT, READFILE, VIEWTOTAL, BOOKUPDATE, WRITEFILE };
enum SELUPDATE { RETURNMAIN, PREVBOOK, NEXTBOOK, INSERTBOOK, ADJUSTBOOK, DELETEBOOK, SEARCHBOOK };
void read_book(BOOK_t* headNode);
void write_book(BOOK_t* headNode);
void update_book(BOOK_t* headNode);
BOOK_t* initailize_DLL(void);
void print_node(BOOK_t* headNode);
void print_one_node(BOOK_t* currentNode);
BOOK_t* new_node(void);
void append_node(BOOK_t* headNode,BOOK_t readNode);
BOOK_t* insert_node(BOOK_t* currentNode);
BOOK_t* delete_node(BOOK_t* currentNode);
BOOK_t* search_node(BOOK_t* headNode,BOOK_t* currentNode);
BOOK_t* adjust_node(BOOK_t* currentNode);
void BM_main(BOOK_t* headNode);
void linePrint(void);
void lineStrPrint(char arr[]);
char* cateEnumToKor(KDC_e cate);
void BM_main(BOOK_t* headNode) //main mneu(도서관리 프로그램)
{
int iSel = 0;
do {
lineStrPrint("도서관리 프로그램");
puts("1 : 도서 자료 읽어 오기");
puts("2 : 도서 현황 보기");
puts("3 : 도서 관리 하기");
puts("4 : 도서 자료 저장 하기");
puts("0 : 종료");
printf(">> ");
scanf_s("%d", &iSel);
switch (iSel)
{
case READFILE:
read_book(headNode);
break;
case VIEWTOTAL:
print_node(headNode);
break;
case BOOKUPDATE:
update_book(headNode);
break;
case WRITEFILE:
write_book(headNode);
break;
case QUIT:
printf("종료 합니다.\n");
break;
default:
printf("잘못된 입력입니다.\n");
break;
}
} while (iSel);
}
void update_book(BOOK_t* headNode) //sub menu(도서 관리 하기)
{
system("cls");
int iUSel = 0;
BOOK_t* currentNode = NULL;
if (headNode->next != NULL) {
currentNode = headNode->next;
}
else {
currentNode = NULL;
}
do {
lineStrPrint("도서 관리 하기");
_LINE;
print_one_node(currentNode);
_LINE;
puts("1 : 이전 도서");
puts("2 : 다음 도서");
puts("3 : 도서 등록");
puts("4 : 도서 수정");
puts("5 : 도서 삭제");
puts("6 : 도서 검색");
puts("0 : 주 메뉴로 돌아가기");
printf(">> ");
scanf_s("%d", &iUSel);
switch (iUSel)
{
case PREVBOOK:
if (currentNode->prev == headNode) {
printf("이전 도서가 존재하지 않습니다.\n");
Sleep(1000);
}
else {
currentNode = currentNode->prev;
}
break;
case NEXTBOOK:
if (currentNode->next == NULL) {
printf("다음 도서가 존재하지 않습니다.\n");
Sleep(1000);
}
else {
currentNode = currentNode->next;
}
break;
case INSERTBOOK:
currentNode = insert_node(currentNode);
break;
case ADJUSTBOOK:
currentNode = adjust_node(currentNode);
break;
case DELETEBOOK:
currentNode = delete_node(currentNode);
break;
case SEARCHBOOK:
currentNode = search_node(headNode,currentNode);
break;
case RETURNMAIN:
printf("주 메뉴로 돌아 갑니다.\n");
Sleep(500);
break;
default:
printf("잘못된 입력입니다.\n");
Sleep(500);
break;
}
system("cls");
} while (iUSel);
}
void read_book(BOOK_t* headNode) //file read & making DDL
{
FILE* fp = NULL;
BOOK_t readNode;
char ReadBuffer[BUFFERSIZE] = { 0 };
fopen_s(&fp, "book_original.txt", "r");
if (fp == NULL) {
printf("File Open Failed.\n");
}
if (headNode->next != NULL) { //이전에 만들어진 DDL이 있으면 삭제
headNode->next = NULL;
}
while (!feof(fp)) {
fscanf_s(fp, "%d %u %s %s %hu\n",
&readNode.eCategory, &readNode.uiCodeNum,
readNode.strBookName, U_SIZEOF(readNode.strBookName),
readNode.strAuthor, U_SIZEOF(readNode.strAuthor),
&readNode.usYear);
readNode.next = NULL;
readNode.prev = NULL;
append_node(headNode, readNode);
}
fclose(fp);
puts("파일 읽기가 완료 되었습니다.");
Sleep(1000);
system("cls");
}
void write_book(BOOK_t* headNode) //text file write
{
FILE* fp = NULL;
BOOK_t* readNode = headNode;
char writeBuffer[BUFFERSIZE] = { 0 };
char strTemp[3][BUFFERSIZE] = { 0 };
fopen_s(&fp, "book.txt", "w");
if (fp == NULL) {
printf("File Write Failed.\n");
}
while (readNode->next != NULL) {
readNode = readNode->next;
sprintf_s(strTemp[0], BUFFERSIZE, "%d", readNode->eCategory); //숫자에서 문자로
sprintf_s(strTemp[1], BUFFERSIZE, "%d", readNode->uiCodeNum);
sprintf_s(strTemp[2], BUFFERSIZE, "%d", readNode->usYear);
fprintf(fp,"%s %s %s %s %s\n",
strTemp[0], strTemp[1], readNode->strBookName, readNode->strAuthor, strTemp[2]);
}
fclose(fp);
puts("파일 쓰기가 완료 되었습니다.");
Sleep(1000);
system("cls");
}
BOOK_t* initailize_DLL(void) //head node
{
BOOK_t* headNode = (BOOK_t*)calloc(1, U_SIZEOF(BOOK_t));
return headNode;
}
BOOK_t* new_node(void) //inser_node/adjust_node에서 사용할 new node input
{
BOOK_t* ptrNode = (BOOK_t*)calloc(1, U_SIZEOF(BOOK_t));
int iCategory = 0;
for (int i = 0; i < 10; i++) {
printf(" [%2d][%11s] %s", i, CAS[i][1], ((i % 3 + 1) == 3) ? "\n" : " || ");
}
puts(" ");
printf("분류 : ");
scanf_s("%d",&iCategory);
ptrNode->eCategory = (KDC_e)iCategory * 100;
printf("코드 : ");
scanf_s("%d", &ptrNode->uiCodeNum);
printf("도서명 : ");
scanf_s("%s", ptrNode->strBookName, U_SIZEOF(ptrNode->strBookName));
printf("저자 : ");
scanf_s("%s", ptrNode->strAuthor, U_SIZEOF(ptrNode->strAuthor));
printf("출판년도 : ");
scanf_s("%hu", &ptrNode->usYear);
return ptrNode;
}
//file read에서 구조체를 받아서 appending node
void append_node(BOOK_t* headNode, BOOK_t readNode)
{
BOOK_t* newNode = (BOOK_t*)calloc(1, U_SIZEOF(BOOK_t)), * app_Node = headNode;
*newNode = readNode;
while (app_Node->next!=NULL){ //searching tail node
app_Node = app_Node->next;
}
//appneding newnode
app_Node->next = newNode;
newNode->prev = app_Node;
}
BOOK_t* insert_node(BOOK_t* currentNode) //current node 다음에 새로운 node를 추가
{
BOOK_t* inserNode = NULL;
system("cls");
lineStrPrint("도서 등록");
inserNode = new_node();
if (currentNode->next != NULL) {
inserNode->prev = currentNode;
inserNode->next = currentNode->next;
currentNode->next->prev = inserNode;
currentNode->next = inserNode;
}
else if(currentNode->next = NULL) {
inserNode->prev = currentNode;
currentNode->next = inserNode;
}
return currentNode->next;
}
BOOK_t* adjust_node(BOOK_t* currentNode) //current node 수정
{
BOOK_t* ptrCurrentNode = NULL;
system("cls");
lineStrPrint("정보 수정");
ptrCurrentNode = new_node(); //new_node로 data를 입력받은 노드
ptrCurrentNode->next = currentNode->next; //new_node의 next를 currentNode에서 받아온다.
ptrCurrentNode->prev = currentNode->prev; //new_node의 prev를 currentNode에서 받아온다.
return ptrCurrentNode;
}
BOOK_t* delete_node(BOOK_t* currentNode) //current node 삭제
{
BOOK_t* delNode = currentNode;
if (currentNode->next != NULL) {
delNode->next->prev = delNode->prev;
delNode->prev->next = delNode->next;
return delNode->next;
}
else{
delNode->prev->next = NULL;
return delNode->prev;
}
free(delNode);
}
//도서명이나 저자명을 선택하여 입력
//찾은 node가 있으면 cuurntnode가 찾은 node로 이동
BOOK_t* search_node(BOOK_t* headNode, BOOK_t* currentNode)
{
int iModeSel = 0, iState = 0;
char strTemp[20] = { 0 };
BOOK_t* ptrSearch = headNode;
if (ptrSearch==NULL){
printf("등록 된 도서가 없습니다.\n");
}
else
{
do {
printf("검색 조건을 입력하세요.\n");
printf("[0] 검색 종료 [1] 도서명 [2] 저자) >> ");
scanf_s("%d", &iModeSel);
switch (iModeSel)
{
case 1:
printf("도서명을 입력하세요 >> ");
scanf_s("%s", strTemp, U_SIZEOF(strTemp));
while (ptrSearch->next!=NULL){
ptrSearch = ptrSearch->next;
if (strcmp(ptrSearch->strBookName, strTemp) == 0) {
iState = 1;
break;
}
}
if (iState == 0) {
puts("검색 결과가 없습니다.");
}
break;
case 2:
printf("저자명을 입력하세요 >> ");
scanf_s("%s", strTemp, U_SIZEOF(strTemp));
while (ptrSearch->next!=NULL){
ptrSearch = ptrSearch->next;
if (strcmp(ptrSearch->strBookName, strTemp) == 0) {
iState = 1;
break;
}
}
if (iState == 0) {
puts("검색 결과가 없습니다.");
}
break;
default:
printf("잘못된 입력입니다.\n");
break;
}
} while (iModeSel && iState!=1);
}
if (iState == 0) {
return currentNode;
}else{
return ptrSearch;
}
}
void print_node(BOOK_t* headNode) //전체 node 출력
{
system("cls");
BOOK_t* ptrPrint = headNode;
lineStrPrint("전체 도서 정보");
printf("%8s\t코드\t%-20s\t%-10s\t출판년도\n","분류","도서명","저자명");
while (ptrPrint->next != NULL) {
ptrPrint = ptrPrint->next;
printf("%8s\t", cateEnumToKor(ptrPrint->eCategory));
printf("%u\t", ptrPrint->uiCodeNum);
printf("%-20s\t", ptrPrint->strBookName);
printf("%-10s\t", ptrPrint->strAuthor);
printf("%8hu\n", ptrPrint->usYear);
}
}
void print_one_node(BOOK_t* currentNode) //node 하나를 화면에 출력(currentnode)
{
if (currentNode != NULL) {
printf("%10s : %s \n", "분류", cateEnumToKor(currentNode->eCategory));
printf("%10s : %04d \n", "코드", currentNode->uiCodeNum);
printf("%10s : %s \n", "도서명", currentNode->strBookName);
printf("%10s : %s \n", "저자", currentNode->strAuthor);
printf("%10s : %d \n", "출판년도", currentNode->usYear);
}
else {
printf("등록 된 도서가 없습니다.");
}
}
void linePrint(void)
{
printf("========================================================================\n");
}
void lineStrPrint(char arr[])
{
_LINE;
printf("\t\t\t%s\n", arr);
_LINE;
}
char* cateEnumToKor(KDC_e cate) //category change from enum to korean
{
static char strArr[20] = { 0 };
for (int i = 0; i < 10; i++) {
if (atoi(CAS[i][0]) == cate) {
strcpy_s(strArr, U_SIZEOF(strArr), CAS[i][1]);
}
}
return strArr;
}
Output
'C\C++' 카테고리의 다른 글
Linked List 회원관리 프로그램 (0) | 2022.03.04 |
---|---|
malloc, realloc 예제 (0) | 2022.03.03 |
포인터 문제 (0) | 2022.03.02 |
배열 문제 (0) | 2022.03.02 |
구조체 문제 (0) | 2022.03.02 |