다음은 이번 실습에서 작성한 도서 관리 프로그램의 소스 코드입니다.
// 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;
}
'C & C++ > 디딤돌 C언어' 카테고리의 다른 글
Part 33. 함수 포인터와 콜백 (1) | 2024.01.23 |
---|---|
Part 32. 도서 관리 프로그램 IV - 저장 및 로드 (1) | 2024.01.23 |
Part 31. 도서 관리 프로그램 III - 도서 추가, 도서 목록, 도서 검색, 장르 삭제 기능 구현 (0) | 2024.01.23 |
Part 30. 도서 관리 프로그램 II - 장르 추가, 전체 장르 보기 (0) | 2024.01.23 |
Part 29. 도서 관리 프로그램 I - 시나리오 및 기본 메뉴 구현 (0) | 2024.01.22 |
Part 28. main 함수 매개 변수 (1) | 2024.01.22 |
Part 27. 파일 입출력 - fread, fwrite, fseek, ftell 함수 (0) | 2024.01.18 |
Part 26. 파일 입출력 함수와 ASCII 문자로 입출력하기 (0) | 2024.01.18 |