본문 바로가기

ETC Programmings

LinkedList를 활용한 도서 관리 프로그램

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {
 struct Book *data;
 struct Node *next;
} node;

typedef struct Book {
 // 제목, 저자, 출판사, 출판일, 가격
 char title[30];
 char author[20];
 char publisher[20];
 int date;
 int price;
};

typedef struct LinkedList {
 int length;
 struct Node *fNode;
}linkedList;

// 1. 기본적인 링크드 리스트 함수
void initList(struct LinkedList*);
node* getNodeAt(struct LinkedList*, int);
void add(struct LinkedList*, struct Book *entryData);
void addInIndex(struct LinkedList*, struct Book*, int);
void erase(struct LinkedList*, int);
void replace(struct LinkedList*, struct Book*, int);
void reset(struct LinkedList*);
void display(struct LinkedList*);
struct Book* get(struct LinkedList*, int);
int isFull(struct LinkedList*);
int isEmpty(struct LinkedList*);
int checkPosition(struct LinkedList*, int);
void displayElement(struct LinkedList*, int);

// 2. UI 함수
void run(struct LinkedList*);
void registBook(struct LinkedList*);
void eraseBook(struct LinkedList*);
void modifyBook(struct LinkedList*);
void replaceItems();
void saveList(struct LinkedList*);
void loadList(struct LinkedList*);
void dataWrite(FILE*, struct LinkedList* , int);
void search(struct LinkedList*);
void searchByTitle(struct LinkedList*);
void searchByAuthor(struct LinkedList*);
void searchByPublisher(struct LinkedList*);
void searchByDate(struct LinkedList*);
void searchByPrice(struct LinkedList*);


// 3. 정렬 함수
void sortByPrice(struct LinkedList*, int, int);
void sortByTitle(struct LinkedList*, int, int);
void sortByAuthor(struct LinkedList*, int, int);
void sortBypublisher(struct LinkedList*, int, int);
void sort(struct LinkedList*);


// 1.기본적인 링크드 리스트 함수
void initList(struct LinkedList* list){
 if(!isEmpty(list))
  reset(list);
 list->length = 0;
 list->fNode = (node *)malloc(sizeof(node));
}

node* getNodeAt(struct LinkedList* list, int index){
 int i;
 node* current = list->fNode;
 for(i = 0 ; i < index ; i++)
 {
  current = current->next;
 }
 return current;
}

void add(struct LinkedList* list, struct Book *entryData){
 node* newNode = (node* )malloc(sizeof(node));
 newNode->data = entryData;
 if(list->length == 0){
  list->fNode = newNode;
 }
 else {
  getNodeAt(list, list->length - 1)->next = newNode;
 }
 list->length +=1;
}

void addInIndex(struct LinkedList* list, struct Book *entryData, int position){
 node* oldNode;
 node* newNode = (node* )malloc(sizeof(node));
 newNode->data = entryData;
 if(checkPosition(list, position)) {
  if (position == list->length)
   add(list, entryData);
  else {
   oldNode = getNodeAt(list, position);
   getNodeAt(list, position - 1)->next = newNode;
   newNode->next = oldNode;
  }
  list->length += 1;
 }
}

void erase(struct LinkedList* list, int position){
 node* tempNode = getNodeAt(list, position);
 if(checkPosition(list, position)) {
  if(position == 0){
   tempNode = tempNode->next;
   free(list->fNode);
   list->fNode = tempNode;
  }
  else if(position != 0 && position == list->length){
   getNodeAt(list, position - 1)->next = NULL;
   free(tempNode);
  }
  else {
   getNodeAt(list, position - 1)->next = getNodeAt(list, position + 1);
   free(tempNode);
  }
  list->length -= 1;
 }
}
void replace(struct LinkedList* list, struct Book *changedData, int position){
 if(checkPosition(list, position))
  getNodeAt(list, position)->data = changedData;
}

void display(struct LinkedList* list){
 if(!isEmpty(list)){
  int i;
  printf("────────────────────────────────────────\n");
  for(i = 0 ; i < list->length; i++) {
   // 제목, 저자, 출판사, 출판일, 가격
   printf(" 제  목 : %s\n", get(list,i)->title);
   printf(" 저  자 : %s\n", get(list,i)->author);
   printf(" 출판사 : %s\n", get(list,i)->publisher);
   printf(" 출판일 : %d\n", get(list,i)->date);
   printf(" 가  격 : %d\n", get(list,i)->price);
   printf("\n");
  }
  printf("────────────────────────────────────────\n");
 }
 printf("\n");
}

void reset(struct LinkedList* list){
 int i;
 for(i = list->length - 1 ; i >= 0; i--) {
  free(getNodeAt(list, i));
 }
}
struct Book* get(struct LinkedList* list, int position){
 if(checkPosition(list, position))
  return getNodeAt(list, position)->data;
 else
  return 0;
}
int isEmpty(struct LinkedList* list){
 return list->length == 0;
}
void displayElement(struct LinkedList* list, int i)
{
 if(!isEmpty(list)){
  printf("────────────────────────────────────────\n");
  printf(" 제  목 : %s\n", get(list,i)->title);
  printf(" 저  자 : %s\n", get(list,i)->author);
  printf(" 출판사 : %s\n", get(list,i)->publisher);
  printf(" 출판일 : %d\n", get(list,i)->date);
  printf(" 가  격 : %d\n", get(list,i)->price);
  printf("\n");
 }
 printf("────────────────────────────────────────\n");
 printf("\n");
}
int checkPosition(struct LinkedList* list, int position){
 return position >= 0 && position < list->length;
}



// 2. UI 함수
void registBook(struct LinkedList* list){
 int hasMore = 0;
 struct Book* book = (struct Book*) malloc(sizeof(struct Book));
 fflush(stdin);
 printf("제목 : "); fflush(stdin); gets(book->title);
 printf("저자 : "); fflush(stdin); gets(book->author);
 printf("출판사 : "); fflush(stdin); gets(book->publisher);
 printf("출판일 : "); scanf("%d", &book->date);
 printf("가격 :  "); scanf("%d", &book->price);
 add(list, book);
 printf("더 입력하실 자료가 있으신가요? 예(1), 아니오(0) : ");
 scanf("%d", &hasMore);
 if(hasMore){
  registBook(list);
 }
}
void eraseBook(struct LinkedList* list){
 int index, sure;
 if(list->length == 0){
  printf("삭제할 자료가 없습니다.");
 }
 else{
  printf("0번 부터 %d번 까지의 자료중 원하시는 자료를 선택하세요 : ", list->length - 1);
  scanf("%d", &index);
  printf("정말 %d번째 자료를 삭제 하시겠습니까? 예(1), 아니오(0)", index);
  scanf("%d", &sure);
  if(sure == 1){
   erase(list, index);
  }
 }
}
void modifyBook(struct LinkedList* list){
 int index = 1;
 int select = 0;
 int sure = 1;
 struct Book* currentBook;
 while(sure){
  printf("0번 부터 %d번 까지의 자료중 원하시는 자료를 선택하세요 : ", list->length - 1);
  scanf("%d", &index);
  currentBook = getNodeAt(list, index)->data;
  printf("제목 :  %s \n", currentBook->title);
  printf("저자 :  %s \n", currentBook->author);
  printf("출판사 : %s \n", currentBook->publisher);
  printf("출판일 : %d \n", currentBook->date);
  printf("가격 :  %d \n", currentBook->price);
  printf("\n");
  printf("*이 자료가 맞습니까? 예(0), 아니오(1), 종료(2)");
  scanf("%d", &sure);
  if(sure == 2) break;
 }
 if(sure == 0){
  printf("변경하시고자 하는 자료값은 무엇입니까? 제목(0), 저자(1), 출판사(2), 출판일(3), 가격(4) ");
  scanf("%d", &select);
  switch(select){
   case 0 : printf("제목 : %s ====>  ", currentBook->title); fflush(stdin); gets(currentBook->title); break;
   case 1 : printf("저자 : %s ====>  ", currentBook->author); fflush(stdin); gets(currentBook->author); break;
   case 2 : printf("출판사 : %s ====>  ", currentBook->publisher); fflush(stdin); gets(currentBook->publisher); break;
   case 3 : printf("출판일 : %d ====> ", currentBook->date); scanf("%d", &currentBook->date); break;
   case 4 : printf("가격 :  %d ====>  ", currentBook->price); scanf("%d", &currentBook->price); break;
   default :   break;
  }
 }
}


void run(struct LinkedList* list){
 // 반드시 Memory Allocation 된 리스트만 들어올 수 있다.
 int status = 1;
 if(list->fNode == NULL){
  initList(list);
 }
 loadList(list);
 printf("───────────────────────\n");
 printf(" 안녕하세요, 도서 목록 데이터베이스 입니다 \n");
 printf("───────────────────────\n");
 while(status != 0){
  printf("  원하시는 메뉴를 선택해주세요\n");
  printf(" ☞ 1. 새로운 도서 추가\n");
  printf(" ☞ 2. 기존 도서 삭제\n");
  printf(" ☞ 3. 기존 도서 변경\n");
  printf(" ☞ 4. 전체 도서 목록 조회\n");
  printf(" ☞ 5. 조건별 도서 조회\n");
  printf(" ☞ 0. 도서 데이터 베이스 종료\n");
  scanf("%d", &status);
  switch(status){
   case 1 : printf("새로운 도서를 추가합니다.\n"); registBook(list); break;
   case 2 : printf("기존 도서를 삭제합니다.\n");  eraseBook(list); break;
   case 3 : printf("기존 도서를 변경합니다.\n");  modifyBook(list); break;
   case 4 : printf("전체 도서를 조회합니다.\n"); display(list); break;
   case 5 : printf("조건별 검색을 합니다.\n"); search(list); break;
   case 0 :
    saveList(list);
    printf("───────────────────────\n");
    printf(" 도서 데이터 베이스를 종료합니다.\n");
    printf("───────────────────────\n");
    break;
   default : printf("존재하지 않는 메뉴입니다. 다시 한번 입력해주세요.\n"); break;
  }
 }
}

void saveList(struct LinkedList* list){
 FILE *fp;
 int i;
 fp = fopen("BookList.txt", "w+");
 fprintf(fp, "%d\n", list->length);
 for(i = 0 ; i < list->length ; i++){
  dataWrite(fp,list, i);
 }
 fclose(fp);
}
void dataWrite(FILE *fp, struct LinkedList* list, int i){
 char delimiter[] = "&";
 int temp;
 fprintf(fp, "%s", get(list, i)->title);
 fprintf(fp, "%s", &delimiter);
 fprintf(fp, "%s", get(list, i)->author);
 fprintf(fp, "%s", &delimiter);
 fprintf(fp, "%s", get(list, i)->publisher);
 fprintf(fp, "%s", &delimiter);
 fprintf(fp, "%d", get(list, i)->date);
 fprintf(fp, "%s", &delimiter);
 fprintf(fp, "%d", get(list, i)->price);
 fprintf(fp, "\n");
}

void loadList(struct LinkedList* list){
 FILE *fp;
 char buffer[1024];
 int i;
 int length;
 char* temp;
 char delimiter[] = "&";
 struct Book* book;
 fp = fopen("BookList.txt", "r");
 fgets(buffer,1024,fp);
 length = atoi(buffer);
 for(i = 0 ; i < length ; i++){
  fgets(buffer,1024,fp);
  book = (struct Book*) malloc(sizeof(struct Book));
  temp = strtok(buffer, "&");
  strcpy(book->title, temp);
  temp = strtok(NULL, "&");
  strcpy(book->author, temp);
  temp = strtok(NULL, "&");
  strcpy(book->publisher, temp);
  temp = strtok(NULL, "&");
  book->date = atoi(temp);
  temp = strtok(NULL, "&");
  book->price = atoi(temp);
  add(list, book);
 }
 fclose(fp);
}
void listWrite(char* buffer, char* delimeter, struct Book* book);
void search(struct LinkedList* list){
 int select;
 printf("원하시는 검색 조건을 선택하세요. 제목별(0), 저자별(1), 출판사(2), 출간일(3), 가격별(4)\n");
 scanf("%d", &select);
 switch(select){
  case 0: searchByTitle(list); return;
  case 1: searchByAuthor(list); return;
  case 2: searchByPublisher(list); return;
  case 3: searchByDate(list); return;
  case 4: searchByPrice(list); return;
  default : printf("잘못된 번호를 선택하셨습니다."); search(list); return;
 }
}
void searchByTitle(struct LinkedList* list){
 int i;
 char keyword[40];
 printf("검색 하고자 하시는 도서의 제목을 입력하세요 :   ");
 fflush(stdin);
 printf("\n");
 gets(keyword);
 printf("검색어 '%s' 로 검색한 결과 입니다\n", keyword);
 for(i = 0; i < list->length ; i++){
  if(strcmp(get(list, i)->title, keyword) == 0)
   displayElement(list, i);
 }
}
void searchByAuthor(struct LinkedList* list){
 int i; char keyword[40];
 printf("검색 하고자 하시는 도서의 제목을 입력하세요 :   ");
 printf("\n");
 fflush(stdin);
 gets(keyword);
 printf("검색어 '%s' 로 검색한 결과 입니다\n", keyword);
 for(i = 0; i < list->length ; i++){
  if(strcmp(get(list, i)->author, keyword) == 0)
   displayElement(list, i);
 }
}
void searchByPublisher(struct LinkedList* list){
 int i; char keyword[40];
 printf("검색 하고자 하시는 도서의 제목을 입력하세요 :   ");
 printf("\n");
 fflush(stdin);
 gets(keyword);
 printf("검색어 '%s' 로 검색한 결과 입니다\n", keyword);
 for(i = 0; i < list->length ; i++){
  if(strcmp(get(list, i)->publisher, keyword) == 0)
   displayElement(list, i);
 }
}
void searchByDate(struct LinkedList* list){
 int i; int keyword;
 printf("검색 하고자 하시는 도서의 제목을 입력하세요 :   ");
 printf("\n");
 scanf("%d",&keyword);
 printf("검색어 '%d' 이후의 도서를 검색합니다.\n", keyword);
 for(i = 0; i < list->length ; i++){
  if(get(list,i)->date > keyword)
   displayElement(list, i);
 }

}
void searchByPrice(struct LinkedList* list){
 int i; int keyword;
 printf("검색 하고자 하시는 도서의 가격을 입력하세요 :   ");
 printf("\n");
 scanf("%d",&keyword);
 printf("검색어 '%d' 원 이하의 도서를 검색합니다.\n", keyword);
 for(i = 0; i < list->length ; i++){
  if(get(list,i)->price <= keyword)
   displayElement(list, i);
 }
}


// 3. 정렬 함수
void sort(struct LinkedList* list){
 int keyword;
 printf("원하는 정렬 기준을 선택 : 가격(0), 제목(1), 저자(2), 출판사(3) \n");
 scanf("%d", &keyword);
 switch(keyword){
  case 0 : sortByPrice(list, 0 , list->length - 1); break;
  case 1 : sortByTitle(list, 0 , list->length - 1); break;
  case 2 : sortByAuthor(list, 0 , list->length - 1); break;
  case 3 : sortBypublisher(list, 0 , list->length - 1); break;
 }
}
void sortByTitle(struct LinkedList* list, int left, int right) {
 int iLeft = left;
 int iRight = right;
 struct Book* temp;
 int tempNum;
 char* pivot;
 if(iLeft >= iRight){
  return; // 재귀함수 종료 조건
 }
 pivot = get(list, (iLeft + iRight) / 2)->title;
 while (iLeft < iRight) {
  while (iLeft < iRight && strcmp(get(list, iLeft)->title, pivot) < 0){
   iLeft += 1;
  }
  while (iLeft < iRight && strcmp(get(list, iRight)->title, pivot) > 0){
   iRight -= 1;
  }
  if (iLeft < iRight){
   temp = get(list, iLeft);
   replace(list, get(list, iRight), iLeft);
   replace(list, temp, iRight);
  }
 }
 if(iRight < iLeft){
  tempNum = iRight;
  iRight = iLeft;
  iLeft = tempNum;
 }
 sortByPrice(list, left, iLeft);
 sortByPrice(list, iLeft == left ? iLeft + 1 : iLeft, right);
}
void sortByAuthor(struct LinkedList* list, int left, int right) {
 int iLeft = left;
 int iRight = right;
 struct Book* temp;
 int tempNum;
 char* pivot;
 if(iLeft >= iRight){
  return; // 재귀함수 종료 조건
 }
 pivot = get(list, (iLeft + iRight) / 2)->author;
 while (iLeft < iRight) {
  while (iLeft < iRight && strcmp(get(list, iLeft)->author, pivot) < 0 ){
   iLeft += 1;
  }
  while (iLeft < iRight && strcmp(get(list, iRight)->author, pivot) >= 0){
   iRight -= 1;
  }
  if (iLeft < iRight){
   temp = get(list, iLeft);
   replace(list, get(list, iRight), iLeft);
   replace(list, temp, iRight);
  }
 }
 if(iRight < iLeft){
  tempNum = iRight;
  iRight = iLeft;
  iLeft = tempNum;
 }
 sortByPrice(list, left, iLeft);
 sortByPrice(list, iLeft == left ? iLeft + 1 : iLeft, right);
}
void sortBypublisher(struct LinkedList* list, int left, int right) {
 int iLeft = left;
 int iRight = right;
 struct Book* temp;
 int tempNum;
 char* pivot;
 if(iLeft >= iRight){
  return; // 재귀함수 종료 조건
 }
 pivot = get(list, (iLeft + iRight) / 2)->publisher;
 while (iLeft < iRight) {
  while (iLeft < iRight && strcmp(get(list, iLeft)->publisher, pivot) < 0){
   iLeft += 1;
  }
  while (iLeft < iRight && strcmp(get(list, iRight)->publisher , pivot) >= 0){
   iRight -= 1;
  }
  if (iLeft < iRight){
   temp = get(list, iLeft);
   replace(list, get(list, iRight), iLeft);
   replace(list, temp, iRight);
  }
 }
 if(iRight < iLeft){
  tempNum = iRight;
  iRight = iLeft;
  iLeft = tempNum;
 }
 sortByPrice(list, left, iLeft);
 sortByPrice(list, iLeft == left ? iLeft + 1 : iLeft, right);

}
void sortByPrice(struct LinkedList* list, int left, int right){
 int iLeft = left;
 int iRight = right;
 struct Book* temp;
 int tempNum;
 int pivot;
 if(iLeft >= iRight){
  return; // 재귀함수 종료 조건
 }
 pivot = get(list, (iLeft + iRight) / 2)->price;
 while (iLeft < iRight) {
  while (iLeft < iRight && get(list, iLeft)->price < pivot){
   iLeft += 1;
  }
  while (iLeft < iRight && get(list, iRight)->price > pivot){
   iRight -= 1;
  }
  if (iLeft < iRight){
   temp = get(list, iLeft);
   replace(list, get(list, iRight), iLeft);
   replace(list, temp, iRight);
  }
 }
 if(iRight < iLeft){
  tempNum = iRight;
  iRight = iLeft;
  iLeft = tempNum;
 }
 sortByPrice(list, left, iLeft);
 sortByPrice(list, iLeft == left ? iLeft + 1 : iLeft, right);
}
void main(void){
 linkedList* list;
 list = (linkedList*) malloc(sizeof(linkedList));
 initList(list);
 run(list);
}


한 일주일 정도를 거쳤을까? 솔직히 코드가 알아보기 힘들다 -_-;;; 가장 난해 했던 포인터 에서 부터, 링크드 리스트를 만들게 해주었던 구조체와 거의 모든 프로그램 언어의 마지막인 입출력까지 하면서 C에 대한 전반적인 내용을 한번 훑을 수 있게 도와주었다. 아직 경미한 수준의 포인터라고 생각하지만.. 내가 '*' 이라는 녀석에 대해서 일단은 지레 겁먹지 않게 되었으니 이제는 좀 괜찮지 않을가? ㅋㅋ

암튼 좋은 경험을 하나 했다... ^^