본문 바로가기

C\C++

도서관리 프로젝트

C_project_도서관리.pptx
2.46MB

 

개요


파일 읽기/쓰기를 이용하여 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