다음은 이번 실습에서 작성한 도서 관리 프로그램의 소스 코드입니다.
// ehcommon.h #pragma once typedef enum _key key; enum _key { NO_DEFINED, F1, F2, F3, F4, F5, F6, F7, F8, F9,F10, ESC }; void clrscr(); int getkey();
//ehcommon.c #pragma warning(disable:4996) #include "ehcommon.h" #include <conio.h> #include <stdio.h> #include <process.h> void clrscr() { system("cls"); } int getkey() { int key = 0; key = getch(); if(key == 27) { return ESC; } if(key == 0) { key = getch(); switch(key) { case 59: return F1;case 60: return F2;case 61: return F3;case 62: return F4; case 63: return F5;case 64: return F6;case 65: return F7;case 66: return F8; case 67: return F9; case 68: return F10; } } return NO_DEFINED; }
// EHArray.h #pragma once typedef struct _EHArray EHArray; typedef void *Element; //요소 형식명을 Element로 정의 typedef Element * Iterator; struct _EHArray { Element *base; //저장소의 위치 정보 int capacity; //현재 저장소의 크기 int size; //현재 보관한 요소 개수 }; EHArray *NewEHArray(int init_capa,Element init_value); //동적으로 배열 생성 void DeleteEHArray(EHArray *arr); //배열 소멸 int EHArrayGetCapacity(EHArray *arr); //저장소의 크기 가져오기 int EHArrayGetSize(EHArray *arr); //보관한 요소 개수 가져오기 void EHArrayPushBack(EHArray *arr,Element data); //순차적으로 자료 보관 Element EHArrayGetAt(EHArray *arr,int index); //보관한 요소 가져오기 void EHArraySetAt(EHArray *arr,int index, Element data); //보관한 요소 설정하기 Iterator EHArrayBegin(EHArray *arr); //저장소의 시작 위치 Iterator EHArrayEnd(EHArray *arr); //저장소의 마지막 위치(보관할 위치) void EHArrayErase(EHArray *arr,Iterator it);//보관한 요소 제거하기
//EHArray.c #include "EHArray.h" #include <stdlib.h> void EHArrayEHArray(EHArray *arr,int init_capa,Element init_value); void EHArrayReserve(EHArray *arr,int capacity); void EHArrayPushBacks(EHArray *arr,int n,Element value); void EHArrayTEHArray(EHArray *arr); EHArray *NewEHArray(int init_capa,Element init_value) { EHArray *arr = (EHArray *)malloc(sizeof(EHArray)); EHArrayEHArray(arr,init_capa,init_value); return arr; } void EHArrayEHArray(EHArray *arr,int init_capa,Element init_value) { arr->base = 0; arr->capacity = 0; arr->size = 0; if(init_capa>0) { EHArrayReserve(arr,init_capa); EHArrayPushBacks(arr,init_capa,init_value); } } void EHArrayReserve(EHArray *arr,int capacity) { arr->base = (Element *)realloc(arr->base,sizeof(Element)*capacity); arr->capacity = capacity; } void EHArrayPushBacks(EHArray *arr,int n,Element value) { int i = 0; for(i=0;i<n;i++) { EHArrayPushBack(arr,value); } } void DeleteEHArray(EHArray *arr) { EHArrayTEHArray(arr); free(arr); } void EHArrayTEHArray(EHArray *arr) { if(arr->base) { free(arr->base); } } int EHArrayGetCapacity(EHArray *arr) { return arr->capacity; } int EHArrayGetSize(EHArray *arr) { return arr->size; } void EHArrayPushBack(EHArray *arr,Element data) { if(arr->capacity == arr->size) { if(arr->capacity) { EHArrayReserve(arr,arr->capacity*2); } else { EHArrayReserve(arr,1); } } arr->base[arr->size] = data; arr->size++; } Element EHArrayGetAt(EHArray *arr,int index) { if((index>=0)&&(index<arr->size)) { return arr->base[index]; } return 0; } void EHArraySetAt(EHArray *arr,int index, Element data) { if((index>=0)&&(index<arr->size)) { arr->base[index] = data; } } Iterator EHArrayBegin(EHArray *arr) { return arr->base; } Iterator EHArrayEnd(EHArray *arr) { return arr->base + arr->size; } void EHArrayErase(EHArray *arr,Iterator it) { Iterator end; arr->size--; end = arr->base + arr->size; for( ; it != end; it++) { (*it) = *(it+1); } }
// Book.h #pragma once #include <stdio.h> typedef struct _Book Book; #define MAX_TNAME_LEN 100 #define MAX_ANAME_LEN 20 struct _Book { char title[MAX_TNAME_LEN+1]; char author[MAX_ANAME_LEN+1]; int bnum; }; Book *NewBook(int bnum,const char *title,const char *author); Book *NewBook2(FILE *fp); void DeleteBook(Book *book); void BookView(Book *book); int BookGetNum(Book *book); const char *BookGetTitle(Book *book); void BookSerialize(Book *book,FILE *fp);
//Book.c #pragma warning(disable:4996) #include "Book.h" #include <stdlib.h> #include <string.h> #include <stdio.h> void BookBook(Book *book,int bnum,const char *title,const char *author); Book *NewBook(int bnum,const char *title,const char *author) { Book *book = 0; book = (Book *)malloc(sizeof(Book)); BookBook(book,bnum,title,author); return book; } void BookDeserialize(Book *book,FILE *fp); Book *NewBook2(FILE *fp) { Book *book = 0; book = NewBook(0,"",""); BookDeserialize(book,fp); return book; } void BookDeserialize(Book *book,FILE *fp) { fread(book,sizeof(Book),1,fp); } void BookBook(Book *book,int bnum,const char *title,const char *author) { book->bnum = bnum; memset(book->title,0,sizeof(book->title)); strncpy(book->title,title,MAX_TNAME_LEN); memset(book->author,0,sizeof(book->author)); strncpy(book->author,author,MAX_ANAME_LEN); } void DeleteBook(Book *book) { free(book); } void BookView(Book *book) { printf("제목:%s\n",book->title); printf("\t도서번호:%d 저자명:%s\n",book->bnum,book->author); } int BookGetNum(Book *book) { return book->bnum; } const char *BookGetTitle(Book *book) { return book->title; } void BookSerialize(Book *book,FILE *fp) { fwrite(book,sizeof(Book),1,fp); }
// Gerne.h #pragma once #include "Book.h" #include "EHArray.h" typedef struct _Genre Genre; #define MAX_GNAME_LEN 20 struct _Genre { char name[MAX_GNAME_LEN+1]; int gnum; int last_bnum; EHArray *books; }; Genre *NewGenre(int gnum,const char *gname); Genre *NewGenre2(FILE *fp); void DeleteGenre(Genre *genre); const char *GenreGetName(Genre *genre); void GenreView(Genre *genre); void GenreAddBook(Genre *genre,const char *title,const char *author); void GenreViewAll(Genre *genre); Book *GenreFindBookByNum(Genre *genre,int bnum); Book *GenreFindBookByTitle(Genre *genre,const char *title); void GenreSerialize(Genre *genre,FILE *fp);
//Genre.c #pragma warning(disable:4996) #include "Genre.h" #include <stdlib.h> #include <string.h> #include <stdio.h> void GenreGenre(Genre *genre,int gnum,const char *gname); Genre *NewGenre(int gnum,const char *gname) { Genre *genre = 0; genre = (Genre *)malloc(sizeof(Genre)); GenreGenre(genre,gnum,gname); return genre; } void GenreGenre(Genre *genre,int gnum,const char *gname) { genre->gnum = gnum; memset(genre->name,0,sizeof(genre->name)); strncpy(genre->name,gname,MAX_GNAME_LEN); genre->books = NewEHArray(0,0); genre->last_bnum = 0; } void GenreDeserialize(Genre *genre,FILE *fp); Genre *NewGenre2(FILE *fp) { Genre *genre = 0; genre = NewGenre(0,""); GenreDeserialize(genre,fp); return genre; } void GenreDeserialize(Genre *genre,FILE *fp) { Book *book=0; int i = 0; int n = 0; fread(genre->name,sizeof(genre->name),1,fp); fread(&(genre->gnum),sizeof(int),1,fp); fread(&(genre->last_bnum),sizeof(int),1,fp); fread(&n,sizeof(int),1,fp); for(i=0 ;i<n; i++) { book = NewBook2(fp); EHArrayPushBack(genre->books,book); } } void GenreTGenre(Genre *genre); void DeleteGenre(Genre *genre) { GenreTGenre(genre); free(genre); } void GenreTGenre(Genre *genre) { Book *book=0; Iterator seek= EHArrayBegin(genre->books); Iterator end= EHArrayEnd(genre->books); for( ;seek != end; ++seek) { book = (Book *)(*seek); DeleteBook(book); } DeleteEHArray(genre->books); } int GenreGetNum(Genre *genre) { return genre->gnum; } const char *GenreGetName(Genre *genre) { return genre->name; } void GenreView(Genre *genre) { printf("장르 번호:%d 장르 이름:%s\n",genre->gnum,genre->name); } void GenreAddBook(Genre *genre,const char *title,const char *author) { Book *book = 0; genre->last_bnum++; book = NewBook(genre->last_bnum,title,author); EHArrayPushBack(genre->books,book); printf("도서번호:%d 로 추가하였습니다.\n",genre->last_bnum); } void GenreViewAll(Genre *genre) { Iterator seek= EHArrayBegin(genre->books); Iterator end= EHArrayEnd(genre->books); Book *sbook=0; GenreView(genre); for( ;seek != end; ++seek) { sbook = (Book *)(*seek); BookView(sbook); } } Book *GenreFindBookByNum(Genre *genre,int bnum) { Iterator seek; Iterator end; Book *book=0; seek= EHArrayBegin(genre->books); end= EHArrayEnd(genre->books); GenreView(genre); for( ;seek != end; ++seek) { book = (Book *)(*seek); if(BookGetNum(book) == bnum) { return book; } } return 0; } Book *GenreFindBookByTitle(Genre *genre,const char *title) { Iterator seek; Iterator end; Book *book=0; const char *stitle = 0; seek= EHArrayBegin(genre->books); end= EHArrayEnd(genre->books); GenreView(genre); for( ;seek != end; ++seek) { book = (Book *)(*seek); stitle = BookGetTitle(book); if(strcmp(stitle,title)==0) { return book; } } return 0; } void GenreSerialize(Genre *genre,FILE *fp) { Iterator seek; Iterator end; Book *book=0; int n = 0; fwrite(genre->name,sizeof(genre->name),1,fp); fwrite(&(genre->gnum),sizeof(int),1,fp); fwrite(&(genre->last_bnum),sizeof(int),1,fp); n = EHArrayGetSize(genre->books); fwrite(&n,sizeof(int),1,fp); seek= EHArrayBegin(genre->books); end= EHArrayEnd(genre->books); for( ;seek != end; ++seek) { book = (Book *)(*seek); BookSerialize(book,fp); } }
//App.h #pragma once typedef struct _App App; #include "Genre.h" #include "EHArray.h" #include <stdio.h> struct _App { char fname[FILENAME_MAX]; int last_gnum; EHArray *genres; }; App *NewApp(const char *fname); void AppRun(App *app); void DeleteApp(App *app);
//App.c #pragma warning(disable:4996) #include "App.h" #include "ehcommon.h" #include <malloc.h> #include <stdio.h> #include <memory.h> #include <string.h> void AppApp(App *app,const char *fname); void AppTApp(App *app); void AppLoad(App *app); void AppSave(App *app); int AppSelectMenu(App *app); void AppAddGenre(App *app); void AppRemoveGenre(App *app); void AppListGenre(App *app); void AppListBookAtGenre(App *app); void AppAddBook(App *app); void AppFindBookByNum(App *app); void AppFindBookByTitle(App *app); void AppListAll(App *app); App *NewApp(const char *fname) { App *app = 0; app = (App *)malloc(sizeof(App)); AppApp(app,fname); return app; } void AppApp(App *app,const char *fname) { memset(app->fname,0,sizeof(app->fname)); strncpy(app->fname,fname,FILENAME_MAX); app->genres = NewEHArray(0,0); app->last_gnum = 0; AppLoad(app); printf("아무 키나 누르세요.\n"); getkey(); } void AppDeserialize(App *app,FILE *fp); void AppLoad(App *app) { FILE *fp = 0; fp = fopen(app->fname,"r"); if(fp) { AppDeserialize(app,fp); } else { printf("환영합니다.\n"); } } void AppDeserialize(App *app,FILE *fp) { int n = 0; int i = 0; Genre *genre=0; fread(&(app->last_gnum),sizeof(int),1,fp); fread(&n,sizeof(int),1,fp); for( i=0 ;i<n;i++) { genre = NewGenre2(fp); EHArrayPushBack(app->genres,genre); } } void AppRun(App *app) { int key = 0; while((key = AppSelectMenu(app))!=ESC) { switch(key) { case F1: AppAddGenre(app); break; case F2: AppRemoveGenre(app); break; case F3: AppListGenre(app); break; case F4: AppListBookAtGenre(app); break; case F5: AppAddBook(app); break; case F6: AppFindBookByNum(app); break; case F7: AppFindBookByTitle(app); break; case F8: AppListAll(app); break; default: printf("잘못 선택하였습니다.\n"); break; } printf("아무 키나 누르세요.\n"); getkey(); } } int AppSelectMenu(App *app) { clrscr(); printf("장르별 도서관리 프로그램 \n"); printf("F1:장르 추가 F2: 장르 삭제 F3: 전체 장르 보기\n"); printf("F4: 특정 장르의 도서 목록 보기\n"); printf("F5:도서 추가 F6: 도서 검색(일련번호) F7: 도서검색(제목)\n"); printf("F8: 전체 도서 보기 ESC: 종료\n"); return getkey(); } Iterator AppFindGenre(App *app,const char *gname); void AppAddGenre(App *app) { char gname[MAX_GNAME_LEN+1]=""; Iterator seek = 0; Genre *genre = 0; printf("%d번째 추가할 장르명을 입력하세요.\n",app->last_gnum+1); gets_s(gname,MAX_GNAME_LEN); seek = AppFindGenre(app,gname); if(seek != EHArrayEnd(app->genres)) { printf("이미 존재하는 장르입니다.\n"); return; } genre = NewGenre(app->last_gnum+1,gname); app->last_gnum++; EHArrayPushBack(app->genres,genre); } Iterator AppFindGenre(App *app,const char *gname) { Iterator seek; Iterator end; Genre *sgenre=0; const char *sgname=0; seek = EHArrayBegin(app->genres); end = EHArrayEnd(app->genres); for( ;seek != end; ++seek) { sgenre = (Genre *)(*seek); sgname = GenreGetName(sgenre); if(strcmp(sgname,gname)==0) { break; } } return seek; } void AppRemoveGenre(App *app) { char gname[MAX_GNAME_LEN+1]=""; Iterator seek = 0; Genre *genre = 0; AppListGenre(app); printf("삭제할 장르명을 입력하세요.\n"); gets_s(gname,MAX_GNAME_LEN); seek = AppFindGenre(app,gname); if(seek == EHArrayEnd(app->genres)) { printf("잘못 선택하였습니다.\n"); return; } genre = (Genre *)(*seek); DeleteGenre(genre); EHArrayErase(app->genres,seek); } void AppListGenre(App *app) { Iterator seek= EHArrayBegin(app->genres); Iterator end= EHArrayEnd(app->genres); Genre *sgenre=0; for( ;seek != end; ++seek) { sgenre = (Genre *)(*seek); GenreView(sgenre); } } void AppListBookAtGenre(App *app) { char gname[MAX_GNAME_LEN+1]=""; Iterator seek = 0; Genre *genre = 0; AppListGenre(app); printf("도서 목록을 확인할 장르명을 입력하세요.\n"); gets_s(gname,MAX_GNAME_LEN); seek = AppFindGenre(app,gname); if(seek == EHArrayEnd(app->genres)) { printf("잘못 선택하였습니다.\n"); return; } genre = (Genre *)(*seek); GenreViewAll(genre); } void AppAddBook(App *app) { char gname[MAX_GNAME_LEN+1]=""; char author[MAX_ANAME_LEN+1]=""; char title[MAX_TNAME_LEN+1]=""; Iterator seek = 0; Genre *genre = 0; AppListGenre(app); printf("도서를 추가할 장르명을 입력하세요.\n"); gets_s(gname,MAX_GNAME_LEN); seek = AppFindGenre(app,gname); if(seek == EHArrayEnd(app->genres)) { printf("잘못 선택하였습니다.\n"); return; } printf("도서명을 입력하세요.\n"); gets_s(title,MAX_TNAME_LEN); printf("저자명을 입력하세요.\n"); gets_s(author,MAX_ANAME_LEN); genre = (Genre *)(*seek); GenreAddBook(genre,title,author); } void AppFindBookByNum(App *app) { char gname[MAX_GNAME_LEN+1]=""; int bnum=0; Iterator seek = 0; Genre *genre = 0; Book *book = 0; AppListGenre(app); printf("검색할 장르명을 입력하세요.\n"); gets_s(gname,MAX_GNAME_LEN); seek = AppFindGenre(app,gname); if(seek == EHArrayEnd(app->genres)) { printf("잘못 선택하였습니다.\n"); return; } printf("도서 번호를 입력하세요.\n"); scanf_s("%d", &bnum); genre = (Genre *)(*seek); book = GenreFindBookByNum(genre,bnum); if(book) { BookView(book); } else { printf("도서를 찾지 못했습니다.\n"); } } void AppFindBookByTitle(App *app) { char gname[MAX_GNAME_LEN+1]=""; char title[MAX_TNAME_LEN+1]=""; Iterator seek = 0; Genre *genre = 0; Book *book = 0; AppListGenre(app); printf("검색할 장르명을 입력하세요.\n"); gets_s(gname,MAX_GNAME_LEN); seek = AppFindGenre(app,gname); if(seek == EHArrayEnd(app->genres)) { printf("잘못 선택하였습니다.\n"); return; } printf("도서 제목을 입력하세요.\n"); gets_s(title,MAX_TNAME_LEN); genre = (Genre *)(*seek); book = GenreFindBookByTitle(genre,title); if(book) { BookView(book); } else { printf("도서를 찾지 못했습니다.\n"); } } void AppListAll(App *app) { Iterator seek= EHArrayBegin(app->genres); Iterator end= EHArrayEnd(app->genres); Genre *genre=0; for( ;seek != end; ++seek) { genre = (Genre *)(*seek); GenreViewAll(genre); } } void DeleteApp(App *app) { AppSave(app); AppTApp(app); free(app); } void AppTApp(App *app) { DeleteEHArray(app->genres); } void AppSerialize(App *app,FILE *fp); void AppSave(App *app) { FILE *fp = 0; fopen_s(&fp, app->fname,"w"); if(fp) { AppSerialize(app,fp); } else { printf("오류!!!데이터 저장 실패\n"); } } void AppSerialize(App *app,FILE *fp) { Iterator seek; Iterator end; int n = 0; Genre *genre=0; fwrite(&(app->last_gnum),sizeof(int),1,fp); n = EHArrayGetSize(app->genres); fwrite(&n,sizeof(int),1,fp); seek= EHArrayBegin(app->genres); end= EHArrayEnd(app->genres); for( ;seek != end; ++seek) { genre = (Genre *)(*seek); GenreSerialize(genre,fp); } }
//Program.c #include "App.h" #define DEF_FNAME "member.ehd" int main(int argc, char **argv) { App *app = 0; if(argc != 2) { app = NewApp(DEF_FNAME); } else { app = NewApp(argv[1]); } AppRun(app); DeleteApp(app); return 0; }