2008. 5. 23. 09:55ㆍETC Programmings
#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", ¤tBook->date); break;
case 4 : printf("가격 : %d ====> ", currentBook->price); scanf("%d", ¤tBook->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에 대한 전반적인 내용을 한번 훑을 수 있게 도와주었다. 아직 경미한 수준의 포인터라고 생각하지만.. 내가 '*' 이라는 녀석에 대해서 일단은 지레 겁먹지 않게 되었으니 이제는 좀 괜찮지 않을가? ㅋㅋ
암튼 좋은 경험을 하나 했다... ^^