이번 강좌에서는
도서 관리 프로그램을 만든다.
안녕하세요 여러분. 지난번 강좌의 마지막 생각하기 문제를 기억하시나요? 일단 이 강의는 여러분이 그 문제에 대해 충분한 시간 노력해서 생각해 보았다는 것을 가정한 하에 진행하도록 하겠습니다.
지난번에 생각해보기 마지막 문제는 아래와 같았습니다.
도서 관리 프로그램을 만들어봅시다. 프로그램에는 다음과 같은 기능들이 구현되어 있어야 합니다. (난이도 : 上)
책을 새로 추가하는 기능 (책의 총 개수는 100 권이라 하자. 이 때, 각 책의 정보는 제목, 저자의 이름, 출판사로 한다)
책의 제목을 검색하면 그 책의 정보가 나와야 한다.
위와 마찬가지로 저자, 출판사 검색 기능이 있어야 한다.
책을 빌리는 기능
책을 반납하는 기능
흠. 여러분은 위들 중 얼마나 해결 하셨나요? 저는 개인적으로 여러분이 위들 중에서 적어도 3 개 이상은 했으리라 믿고 싶습니다. 만일 그렇지 않다면 이 강의를 얼른 닫아서 다시 생각해보도록 하세요.
프로그램을 어떻게 만들 것인가?
사실 여러분이 이 문제를 해결했을 때 많은 어려움이 있었을 것이라 생각합니다. 왜냐하면 여러분은 아직까지 조그마한 작업들을 하는 프로그램만을 만들었지 이렇게 거대한(?) 프로그램은 만들어보지 않았기 때문이죠. 이렇게 거대한 프로그램을 만들 때면 이전의 작은 프로그램들을 만들때와는 달리 체계적으로 계획을 세우는 자세가 필요합니다.
이 때, 체계적으로 계획을 세우는 자세란 다음을 모두 생각해보는 것입니다.
이 프로그램은 무슨 작업을 하는가? 과연 이 작업이 꼭 필요한 것인가? (만일 그렇지 않다면 (1) 로 되돌아갑니다) 어떠한 환경에서 프로그램이 작동되는가? 무슨 언어로 개발할 것인가?
정도로 되겠습니다. 일단 1 번의 경우 프로그램을 계획하는 단계에서 가장 중요한 부분 중에 하나 입니다. 우리가 만들 프로그램의 경우 “도서 관리 프로그램” 입니다. 이 도서 관리 프로그램에는 정말 도서를 관리하는데 꼭 필요한 기능들 만이 들어가야 되겠지요. 예를 들면 제가 위해서 요구한 것들이지요. 만일 쓸데 없는 작업들을 많이 넣게 되면 프로그램 용량도 커질 뿐더러 개발하는데 드는 시간도 많이 들기 때문에 좋지 않습니다.
2 번의 경우 1 번에서 내가 한 것들을 확인하는 단계입니다. 필요 없는 기능이나 꼭 필요하지 않거나, 아니면 이 프로그램의 목적과 부합하지 않는 작업들의 경우 다시 1 번으로 돌아가 생각해 보아야할 필요성이 있습니다. 우리가 만들어야 할 도서프로그램은 제가 요구한 조건 만을 만들어 주면 충분합니다.
3 번은 우리에게는 큰 문제가 아니지만 실제로 프로그램을 개발하게 되면 상당히 중요한 역할을 차지합니다. 우리가 만드는 프로그램은 Windows 에서 작동될 수 도 있고 Linux 나 MacOS 에서 작동될 수 도 있습니다. 아니면 TV 나 냉장고 아니면 세탁기와 같은 가전 제품에서도 작동될 수 있고 요즘 가장 화제가 되는 iPhone 과 같은 스마트 폰에서 작동될 수 도 있습니다.
우리는 이러한 프로그램의 작동 환경에 맞추어 프로그램을 어떻게 만들어야 될지 고민해야 합니다. 예를 들어 은행의 ATM 에서 작동되는 프로그램은 보안이 최고로 우선이어야 겠죠. 비교적 속도가 느리더라도 말이죠. iPhone 과 같은 스마트 폰에서 작동하는 프로그램은 스마트폰의 사양이 보통 PC 보다 좋지 않으므로 프로그램을 가볍고 빠르게 만들어야 합니다. 우리가 만들 도서 관리 프로그램은 그냥 Windows 에서만 작동되도 충분합니다
4 번은 프로그램을 어떠한 언어 (물론 우리의 경우 무조건 C 이지만…) 로 만들지 결정하는 단계입니다. 세상에서는 수 많은 언어들이 있는데 우리가 지금 배우는 C 말고도 (물론 C 가 가장 기본적이면서도 중요한 언어지요^^) 각각의 특성을 가지는 언어들이 많습니다. 우리는 이 때 마다 1,2,3 번을 충분히 고려하여 가장 효율적인 언어를 선택해서 프로그램을 만들어야 겠지요. 물론 우리가 만들 도서 프로그램은 C 언어로 만듭니다.
프로그램의 기본 뼈대
자. 그럼 무슨 작업을 하는 프로그램을 만들지 정했으니 이제, 어떠한 방식으로 작동되는지 생각해보도록 합시다. 우리가 만들어야 할 프로그램은 단순히 C 언어 프로그래밍 실력을 키우기 위한 것이기 때문이 굳이 예쁘게 까지 만들 필요는 없을 것 같습니다. 따라서, 이 도서 관리 프로그램은 매우 단순하게, 첫 화면에서 메뉴를 입력 받고 입력 받은 작업을 수행 한 후 다시 메뉴로 돌아오는 것으로 하면 될 것 같습니다.
따라서 프로그램의 기본 뼈대는 아래 처럼 만들 수 있습니다. (물론 여러분이 하신 방법도 좋은 방법 일 것입니다. 제 방법은 단순히 참고로만 알아두세요)
#include int main () { int user_choice; /* 유저가 선택한 메뉴*/ while ( 1 ) { printf ( “도서 관리 프로그램
” ); printf ( “메뉴를 선택하세요
” ); printf ( “1. 책을 새로 추가하기
” ); printf ( “2. 책을 검색하기
” ); printf ( “3. 책을 빌리기
” ); printf ( “4. 책을 반납하기
” ); printf ( “5. 프로그램 종료
” ); printf ( “당신의 선택은 : ” ); scanf ( “%d” , & user_choice); if (user_choice == 1 ) { /* 책을 새로 추가하는 함수 호출 */ } else if (user_choice == 2 ) { /* 책을 검색하는 함수 호출 */ } else if (user_choice == 3 ) { /* 책을 빌리는 함수 호출 */ } else if (user_choice == 4 ) { /* 책을 반납하는 함수 호출 */ } else if (user_choice == 5 ) { /* 프로그램을 종료한다. */ break ; } } return 0 ; }
성공적으로 컴파일 하면
실행 결과
도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 1 도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 5
소스 코드에는 특별히 어려운 부분이 없으나 혹시 다음 문장이 무슨 뜻인지 모를 수 있을 것입니다.
while ( 1 )
위 말은, 이전에도 이야기 했듯이 컴퓨터는 0 을 거짓, 0 이 아닌 값을 참 으로 판별한다고 말했습니다. 따라서 while 문의 조건이 1 이므로, 다시 말하면 while 문의 조건이 언제나 참이라는 것이지요. 따라서 이 while 문은 무한히 반복되게 됩니다. 우리가 break 를 하지 않을 경우 말이죠.
위 소스 코드에서 중요한 점은 각 작업을 선택할 때 마다 이에 해당하는 ‘함수’ 를 호출한다는 점입니다. 물론, 함수를 반드시 호출할 필요는 없습니다. 그냥 if 문 안에다가 위 작업을 처리하는 코드를 열심히 적어주면 되지요. 하지만 함수를 호출하게 되면 코드를 보기에 상당히 깔끔하며 이해도 잘됩니다.
이 프로그램에 필요한 변수는?
기본적으로 생각해 보아도 책의 제목, 출판사의 이름, 저자의 이름을 저장할 배열이 있어야 합니다. 또한 현재 이 책의 상태 (빌려갔는지, 안 빌려갔는지) 를 표시할 수 있는 배열도 필요합니다. 마지막으로 현재 책의 총 개수가 있어야지만 나중에 책을 새로 추가할 때 배열의 몇 번째 원소에 표시할 지 알 수 있습니다. 따라서 이들을 조합하면 다음과 같이 변수를 선언할 수 있습니다.
int user_choice; /* 유저가 선택한 메뉴 */ int num_total_book = 0 ; /* 현재 책의 수 */ /* 각각 책, 저자, 출판사를 저장할 배열 생성. 책의 최대 개수는 100 권*/ char book_name[ 100 ][ 30 ], auth_name[ 100 ][ 30 ], publ_name[ 100 ][ 30 ]; /* 빌렸는지 상태를 표시 */ int borrowed[ 100 ];
이 때 book_name 의 크기가 [100][30] 인 이유는 이전에도 말했듯이 이 도서프로그램에 들어갈 수 있는 책의 최대 개수는 100 권이고, 제목의 크기는 최대 30 자로 제한되기 때문이죠. 나머지 변수들도 마찬가지 입니다. 이 때 borrowed 배열의 경우 원소의 값이 1 이면 빌림, 0 이면 빌리지 않음 이라고 생각하시면 됩니다.
이제 무슨 변수가 필요한지도 알았으니 먼저 1 번 작업, 즉 책을 새로 추가하는 함수를 만들어보도록 합시다. 이름은 add_book 이고 리턴형은 int 로 합시다.
/* 책을 추가하는 함수*/ int add_book () {}
일단 함수를 만들기 전에 인자로 무엇을 받아야 하는지 생각해봅시다. 책을 추가하려면 책의 이름, 출판사, 저자를 저장할 배열에 대한 포인터를 인자로 받아야 합니다. 그래야지만 이 배열에 새로운 책의 정보를 추가할 수 있지요. 또한 borrowed 배열도 인자로 받아서 기본 설정을 해주어야 합니다. 물론 borrowed 배열의 기본 값은 0, 즉 빌려가지 않음 이겠지요. 마지막으로 num_total_book 도 필요합니다. 왜냐하면 현재 책의 총 수를 알아야 배열의 몇번째 원소에 값을 집어 넣을 지 알게 되기 때문이죠.
이를 종합하여 인자를 만들어보면
int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book) {}
참고로 팁으로 알려주는 사실은 위와 같이 인자를 쓰는 부분에 엔터를 쳐도 큰 문제는 없습니다. 왜냐하면 C 언어는 위 인자들이 같은 문장에 나열되어 있다고 생각하기 때문이죠. 인자가 길어져서 보기 흉할 때 자주 쓰는 방법 입니다. 자, 그럼 얼른 add_book 함수를 완성시켜봅시다. add_book 함수는 매우 간단합니다.
/* 책을 추가하는 함수*/ int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book) { printf ( “추가할 책의 제목 : ” ); scanf ( “%s” , book_name[ * num_total_book]); printf ( “추가할 책의 저자 : ” ); scanf ( “%s” , auth_name[ * num_total_book]); printf ( “추가할 책의 출판사 : ” ); scanf ( “%s” , publ_name[ * num_total_book]); borrowed[ * num_total_book] = 0 ; /* 빌려지지 않음*/ printf ( “추가 완료!
” ); ( * num_total_book) ++ ; return 0 ; }
저는 위와 같이 하였습니다.
이제 add_book 함수를 이용하기 위해 main 함수의 if (user_choice == 1) 부분에 add_book 함수를 호출하는 코드를 넣어 주시면 됩니다. 아래와 같이 말이지요.
#include int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book); int main () { int user_choice; /* 유저가 선택한 메뉴 */ int num_total_book = 0 ; /* 현재 책의 수 */ /* 각각 책, 저자, 출판사를 저장할 배열 생성. 책의 최대 개수는 100 권*/ char book_name[ 100 ][ 30 ], auth_name[ 100 ][ 30 ], publ_name[ 100 ][ 30 ]; /* 빌렸는지 상태를 표시 */ int borrowed[ 100 ]; while ( 1 ) { printf ( “도서 관리 프로그램
” ); printf ( “메뉴를 선택하세요
” ); printf ( “1. 책을 새로 추가하기
” ); printf ( “2. 책을 검색하기
” ); printf ( “3. 책을 빌리기
” ); printf ( “4. 책을 반납하기
” ); printf ( “5. 프로그램 종료
” ); printf ( “당신의 선택은 : ” ); scanf ( “%d” , & user_choice); if (user_choice == 1 ) { /* 책을 새로 추가하는 함수 호출 */ add_book (book_name, auth_name, publ_name, borrowed, & num_total_book); } else if (user_choice == 2 ) { /* 책을 검색하는 함수 호출 */ } else if (user_choice == 3 ) { /* 책을 빌리는 함수 호출 */ } else if (user_choice == 4 ) { /* 책을 반납하는 함수 호출 */ } else if (user_choice == 5 ) { /* 프로그램을 종료한다. */ break ; } } return 0 ; } /* 책을 추가하는 함수*/ int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book) { printf ( “추가할 책의 제목 : ” ); scanf ( “%s” , book_name[ * num_total_book]); printf ( “추가할 책의 저자 : ” ); scanf ( “%s” , auth_name[ * num_total_book]); printf ( “추가할 책의 출판사 : ” ); scanf ( “%s” , publ_name[ * num_total_book]); borrowed[ * num_total_book] = 0 ; /* 빌려지지 않음*/ printf ( “추가 완료!
” ); ( * num_total_book) ++ ; return 0 ; }
성공적으로 컴파일 했으면
실행 결과
도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 1 추가할 책의 제목 : The_C_Language 추가할 책의 저자 : Psi 추가할 책의 출판사 : itguru 추가 완료! 도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 5
어때요. 프로그램이 아주 잘 작동하고 있는 것 같네요. main 함수의 if 문에서 주의해야 할 점은
add_book (book_name, auth_name, publ_name, borrowed, & num_total_book);
과 같이 & 를 어디에 붙일지 매우 헷갈린다는 것입니다. 기본적으로 배열의 경우, 배열의 이름이 배열의 메모리 상의 시작 주소 이기 때문에 & 를 붙일 필요가 없습니다. (정확히 말하면 붙이면 안됩니다). 그러나 num_total_book 과 같은 int 형 변수의 경우 int* 포인터에 주소값을 전달하려면 & 를 이용하여 num_total_book 변수의 주소값을 전달 해주어야 합니다.
또 하나 주의해야 할 부분은 add_book 함수의 원형에서
int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book);
와 같이 해야 하는데 마지막의 세미 콜론을 빠뜨리게 되면
컴파일 오류
error C2085: ‘main’ : 정식 매개 변수 목록에 없습니다. error C2143: 구문 오류 : ‘;’이(가) ‘{‘ 앞에 없습니다. error C2082: ‘num_total_book’ 정식 매개 변수 재정의 error C2082: ‘book_name’ 정식 매개 변수 재정의 error C2082: ‘auth_name’ 정식 매개 변수 재정의 error C2082: ‘publ_name’ 정식 매개 변수 재정의 error C2082: ‘borrowed’ 정식 매개 변수 재정의 warning C4047: ‘함수’ : ‘int *’의 간접 참조 수준이 ‘int **’과(와) 다릅니다. warning C4024: ‘add_book’ : 형식 및 실제 매개 변수 5의 형식이 서로 다릅니다. error C2084: ‘int add_book(char (*)[30],char (*)[30],char (*)[30],int *,int *)’ 함수에 이미 본문이 있습니다.
와 같이 이해하기 힘든 오류의 향연을 맛보게 됩니다.
책 검색하기
자. 이번에는 두 번째 작업, 책을 검색하는 작업을 수행하는 함수를 만들어보기로 합시다. 이 함수의 이름은 serach_book 이라고 합시다. 그렇다면 이 함수는 어떠한 인자를 취해야 될까요? 일단, 단순히 생각해 보아도 book_name, auth_name, publ_name 은 모두 취해야 될 것 같네요. 왜냐하면 우리가 검색을 수행 시, 책 제목에서, 지은이 이름에서, 출판사 이름에서 중 어느 하나를 선택해서 검색할 것이기 때문이죠. 또한 전체 책의 총 개수도 필요합니다. 검색할 때 불필요한 부분은 찾지 않게 하기 말이죠. 결과적으로 함수의 인자는 아래와 같으면 충분하다는 사실을 알 수 있습니다.
int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book)
참고로, 우리가 도서 관리 프로그램에서 만들 “검색” 기능은 우리가 알고 있는 검색 기능과는 살짝 다릅니다. 우리가 흔히 쓰는 검색 기능은 문자열이 비슷하거나 형태를 포함해도 검색 결과에 나타나지만 우리가 만들 검색 기능은 문자열이 완전히 같을 때 나타난다고 합시다. (나중에 업그레이드시 이 부분도 고려해서 하도록 합시다)
그렇다면 머리속에 번뜩이는 생각은 아마,
” 지난번 강좌에서 만들었던 문자열 비교 함수를 이용하면 되겠네!”
그럼, 지난번 강좌에서 문자열 비교 함수 코드를 복사해오겠습니다.
int compare ( char * str1, char * str2) { while ( * str1) { if ( * str1 != * str2) { return 0 ; } str1 ++ ; str2 ++ ; } if ( * str2 == ‘\0’ ) return 1 ; return 0 ; }
이렇게 미리 만들어놓은 소스 코드를 이용하는 것도 매우 중요한 기술중에 하나 입니다. 이미 만든 것을 또 만드느랴 시간을 굳이 낭비할 필요가 없게 되죠.
이번에는 book_search 함수에 어떠한 변수들이 필요할지 생각해봅시다. (굳이 지금 변수들이 뭐가 필요하나 생각을 안해도 됩니다. 저 역시 프로그래밍을 하다가 필요한 변수들이 있으면 그때 그때 추가하는 스타일 입니다. 여기서 집고 넘어가는 것은 기본적으로 무슨 변수들이 필요할 지 생각해 보는 것입니다)
먼저, 사용자의 검색어를 받는 배열이 필요합니다. 따라서 나중에 이 검색어와 책 정보를 비교할 수 있겠지요. 또한 사용자가 어떠한 검색을 할지 (책 제목 검색, 지은이 검색, 출판사 검색) 선택을 할 때도 변수가 필요합니다. 마지막으로 첫번째 책 부터 num_total_book 번째 책 까지 책 정보를 비교하기 현재 몇 번째 책의 정보와 검색어를 비교하고 있는지에 대한 변수가 필요합니다.
그렇다면 아래와 같이 되겠군요.
int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; /* 사용자가 입력한 검색어 */
자 이제, 사용자로 부터 입력을 받아 봅시다.
int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book) { int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; printf ( “어느 것으로 검색 할 것인가요?
” ); printf ( “1. 책 제목 검색
” ); printf ( “2. 지은이 검색
” ); printf ( “3. 출판사 검색
” ); scanf ( “%d” , & user_input); printf ( “검색할 단어를 입력해주세요 : ” ); scanf ( “%s” , user_search); return 0 ; }
자. 그럼 사용자로 부터 검색어 까지 입력을 받았으니 검색어를 처리하는 일만 남았습니다. 사실 ‘검색’ 이란 말이 거창해 보이지만 우리가 만들 도서 프로그램에서는 상당히 단순합니다. 단순히 compare 함수를 이용해서 책 제목 검색을 했다면, 각 책들의 제목과 user_search 와 비교하면 되는 것이지요. 이 아이디어를 바탕으로 만들면 다음과 같이 됩니다.
int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book) { int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; printf ( “어느 것으로 검색 할 것인가요?
” ); printf ( “1. 책 제목 검색
” ); printf ( “2. 지은이 검색
” ); printf ( “3. 출판사 검색
” ); scanf ( “%d” , & user_input); printf ( “검색할 단어를 입력해주세요 : ” ); scanf ( “%s” , user_search); printf ( “검색 결과
” ); if (user_input == 1 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 책 제목을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (book_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 2 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 지은이 이름을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (auth_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 3 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 출판사를 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (publ_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } return 0 ; }
어때요? 소스가 그다지 어렵지 않죠? 위 소스코드에 대한 해석은 여태까지 강좌를 정말 보았다고 한 사람이라면 이해할 수 있을 것입니다. 그럼, 다시 main 함수에 search_book 함수를 적용시켜 봅시다.
#include int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book); int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book); int compare ( char * str1, char * str2); int main () { int user_choice; /* 유저가 선택한 메뉴 */ int num_total_book = 0 ; /* 현재 책의 수 */ /* 각각 책, 저자, 출판사를 저장할 배열 생성. 책의 최대 개수는 100 권*/ char book_name[ 100 ][ 30 ], auth_name[ 100 ][ 30 ], publ_name[ 100 ][ 30 ]; /* 빌렸는지 상태를 표시 */ int borrowed[ 100 ]; while ( 1 ) { printf ( “도서 관리 프로그램
” ); printf ( “메뉴를 선택하세요
” ); printf ( “1. 책을 새로 추가하기
” ); printf ( “2. 책을 검색하기
” ); printf ( “3. 책을 빌리기
” ); printf ( “4. 책을 반납하기
” ); printf ( “5. 프로그램 종료
” ); printf ( “당신의 선택은 : ” ); scanf ( “%d” , & user_choice); if (user_choice == 1 ) { /* 책을 새로 추가하는 함수 호출 */ add_book (book_name, auth_name, publ_name, borrowed, & num_total_book); } else if (user_choice == 2 ) { /* 책을 검색하는 함수 호출 */ search_book (book_name, auth_name, publ_name, num_total_book); } else if (user_choice == 3 ) { /* 책을 빌리는 함수 호출 */ } else if (user_choice == 4 ) { /* 책을 반납하는 함수 호출 */ } else if (user_choice == 5 ) { /* 프로그램을 종료한다. */ break ; } } return 0 ; } /* 책을 추가하는 함수*/ int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book) { printf ( “추가할 책의 제목 : ” ); scanf ( “%s” , book_name[ * num_total_book]); printf ( “추가할 책의 저자 : ” ); scanf ( “%s” , auth_name[ * num_total_book]); printf ( “추가할 책의 출판사 : ” ); scanf ( “%s” , publ_name[ * num_total_book]); borrowed[ * num_total_book] = 0 ; /* 빌려지지 않음*/ printf ( “추가 완료!
” ); ( * num_total_book) ++ ; return 0 ; } /* 책을 검색하는 함수 */ int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book) { int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; printf ( “어느 것으로 검색 할 것인가요?
” ); printf ( “1. 책 제목 검색
” ); printf ( “2. 지은이 검색
” ); printf ( “3. 출판사 검색
” ); scanf ( “%d” , & user_input); printf ( “검색할 단어를 입력해주세요 : ” ); scanf ( “%s” , user_search); printf ( “검색 결과
” ); if (user_input == 1 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 책 제목을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (book_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 2 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 지은이 이름을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (auth_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 3 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 출판사를 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (publ_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } return 0 ; } int compare ( char * str1, char * str2) { while ( * str1) { if ( * str1 != * str2) { return 0 ; } str1 ++ ; str2 ++ ; } if ( * str2 == '\0' ) return 1 ; return 0 ; }
성공적으로 컴파일 했다면
실행 결과
도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 2 어느 것으로 검색 할 것인가요? 1. 책 제목 검색 2. 지은이 검색 3. 출판사 검색 2 검색할 단어를 입력해주세요 : Psi 검색 결과 번호 : 0 // 책 이름 : The_C_Language // 지은이 : Psi // 출판사 : itguru 번호 : 1 // 책 이름 : AdvancedCProgramming // 지은이 : Psi // 출판사 : modoocode 도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 5
위와 같이 아주 잘 작동함을 알 수 있습니다.
아마도 위 도서 프로그램에서는 검색하기 기능이 가장 어려운 것 같네요. 나머지 기능들은 정말로 단순합니다. 3 번째 기능인 "책을 빌리기" 는 단순히 사용자가 빌리려는 책의 번호를 입력하면 borrowed 배열의 책 번호에 위치한 원소의 값을 0 에서 1 로 바꾸어주면 됩니다. 왜냐하면 borrowed 가 1 이면 빌려진 것, 0 이 면 안 빌려진 것 이기 때문이죠. 마찬가지로 책을 반납하는 기능도 만들 수 있습니다.
3, 4 번 기능
먼저, 3 번 기능 부터 만들어봅시다. 함수 이름은 borrow_book 으로 합시다.
int borrow_book ( int * borrowed) { /* 사용자로 부터 책번호를 받을 변수*/ int book_num; printf ( "빌릴 책의 번호를 말해주세요
" ); printf ( "책 번호 : " ); scanf ( "%d" , & book_num); if (borrowed[book_num] == 1 ) { printf ( "이미 대출된 책입니다!
" ); } else { printf ( "책이 성공적으로 대출되었습니다.
" ); borrowed[book_num] = 1 ; } return 0 ; }
사실 위 함수는 매우 매우 간단하므로 특별히 설명할 것은 없습니다. 다만 주의할 점은 책이 이미 대출되어 있는 경우에도 처리를 잘 해주어야 한다는 점입니다. 책이 대출되어 있을 경우 "이미 대출된 책입니다" 라는 메세지를 표시하고 대출을 시키면 안됩니다. 자, 그럼 이제 위 함수를 main 함수에 넣어 작동시켜 봅시다.
#include int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book); int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book); int compare ( char * str1, char * str2); int borrow_book ( int * borrowed); int main () { int user_choice; /* 유저가 선택한 메뉴 */ int num_total_book = 0 ; /* 현재 책의 수 */ /* 각각 책, 저자, 출판사를 저장할 배열 생성. 책의 최대 개수는 100 권*/ char book_name[ 100 ][ 30 ], auth_name[ 100 ][ 30 ], publ_name[ 100 ][ 30 ]; /* 빌렸는지 상태를 표시 */ int borrowed[ 100 ]; while ( 1 ) { printf ( “도서 관리 프로그램
” ); printf ( “메뉴를 선택하세요
” ); printf ( “1. 책을 새로 추가하기
” ); printf ( “2. 책을 검색하기
” ); printf ( “3. 책을 빌리기
” ); printf ( “4. 책을 반납하기
” ); printf ( “5. 프로그램 종료
” ); printf ( “당신의 선택은 : ” ); scanf ( “%d” , & user_choice); if (user_choice == 1 ) { /* 책을 새로 추가하는 함수 호출 */ add_book (book_name, auth_name, publ_name, borrowed, & num_total_book); } else if (user_choice == 2 ) { /* 책을 검색하는 함수 호출 */ search_book (book_name, auth_name, publ_name, num_total_book); } else if (user_choice == 3 ) { /* 책을 빌리는 함수 호출 */ borrow_book (borrowed); } else if (user_choice == 4 ) { /* 책을 반납하는 함수 호출 */ } else if (user_choice == 5 ) { /* 프로그램을 종료한다. */ break ; } } return 0 ; } /* 책을 추가하는 함수*/ int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book) { printf ( “추가할 책의 제목 : ” ); scanf ( “%s” , book_name[ * num_total_book]); printf ( “추가할 책의 저자 : ” ); scanf ( “%s” , auth_name[ * num_total_book]); printf ( “추가할 책의 출판사 : ” ); scanf ( “%s” , publ_name[ * num_total_book]); borrowed[ * num_total_book] = 0 ; /* 빌려지지 않음*/ printf ( “추가 완료!
” ); ( * num_total_book) ++ ; return 0 ; } /* 책을 검색하는 함수 */ int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book) { int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; printf ( “어느 것으로 검색 할 것인가요?
” ); printf ( “1. 책 제목 검색
” ); printf ( “2. 지은이 검색
” ); printf ( “3. 출판사 검색
” ); scanf ( “%d” , & user_input); printf ( “검색할 단어를 입력해주세요 : ” ); scanf ( “%s” , user_search); printf ( “검색 결과
” ); if (user_input == 1 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 책 제목을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (book_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 2 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 지은이 이름을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (auth_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 3 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 출판사를 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (publ_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } return 0 ; } int compare ( char * str1, char * str2) { while ( * str1) { if ( * str1 != * str2) { return 0 ; } str1 ++ ; str2 ++ ; } if ( * str2 == '\0' ) return 1 ; return 0 ; } int borrow_book ( int * borrowed) { /* 사용자로 부터 책번호를 받을 변수*/ int book_num; printf ( "빌릴 책의 번호를 말해주세요
" ); printf ( "책 번호 : " ); scanf ( "%d" , & book_num); if (borrowed[book_num] == 1 ) { printf ( "이미 대출된 책입니다!
" ); } else { printf ( "책이 성공적으로 대출되었습니다.
" ); borrowed[book_num] = 1 ; } return 0 ; }
성공적으로 컴파일 했다면
실행 결과
메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 3 빌릴 책의 번호를 말해주세요 책 번호 : 0 책이 성공적으로 대출되었습니다. 도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 5
위와 같이 책이 잘 대출됨을 알 수 있습니다.
마찬가지 아이디어를 이용해서 책을 반납하는 함수를 만들어봅시다. 함수의 이름은 return_book 으로 합시다. 이 역시 borrow_book 과 하는 일이 거의 똑같으므로 설명을 생략하도록 하겠습니다.
int return_book ( int * borrowed) { /* 반납할 책의 번호 */ int num_book; printf ( "반납할 책의 번호를 써주세요
" ); printf ( "책 번호 : " ); scanf ( "%d" , & num_book); if (borrowed[num_book] == 0 ) { printf ( "이미 반납되어 있는 상태입니다
" ); } else { borrowed[num_book] = 0 ; printf ( "성공적으로 반납되었습니다
" ); } return 0 ; }
역시 간단하군요. borrow_book 함수의 거의 똑같습니다. 이제, 이 함수를 main 함수에 넣어 봅시다.
#include int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book); int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book); int compare ( char * str1, char * str2); int borrow_book ( int * borrowed); int return_book ( int * borrowed); int main () { int user_choice; /* 유저가 선택한 메뉴 */ int num_total_book = 0 ; /* 현재 책의 수 */ /* 각각 책, 저자, 출판사를 저장할 배열 생성. 책의 최대 개수는 100 권*/ char book_name[ 100 ][ 30 ], auth_name[ 100 ][ 30 ], publ_name[ 100 ][ 30 ]; /* 빌렸는지 상태를 표시 */ int borrowed[ 100 ]; while ( 1 ) { printf ( “도서 관리 프로그램
” ); printf ( “메뉴를 선택하세요
” ); printf ( “1. 책을 새로 추가하기
” ); printf ( “2. 책을 검색하기
” ); printf ( “3. 책을 빌리기
” ); printf ( “4. 책을 반납하기
” ); printf ( “5. 프로그램 종료
” ); printf ( “당신의 선택은 : ” ); scanf ( “%d” , & user_choice); if (user_choice == 1 ) { /* 책을 새로 추가하는 함수 호출 */ add_book (book_name, auth_name, publ_name, borrowed, & num_total_book); } else if (user_choice == 2 ) { /* 책을 검색하는 함수 호출 */ search_book (book_name, auth_name, publ_name, num_total_book); } else if (user_choice == 3 ) { /* 책을 빌리는 함수 호출 */ borrow_book (borrowed); } else if (user_choice == 4 ) { /* 책을 반납하는 함수 호출 */ return_book (borrowed); } else if (user_choice == 5 ) { /* 프로그램을 종료한다. */ break ; } } return 0 ; } /* 책을 추가하는 함수*/ int add_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int * borrowed, int * num_total_book) { printf ( “추가할 책의 제목 : ” ); scanf ( “%s” , book_name[ * num_total_book]); printf ( “추가할 책의 저자 : ” ); scanf ( “%s” , auth_name[ * num_total_book]); printf ( “추가할 책의 출판사 : ” ); scanf ( “%s” , publ_name[ * num_total_book]); borrowed[ * num_total_book] = 0 ; /* 빌려지지 않음*/ printf ( “추가 완료!
” ); ( * num_total_book) ++ ; return 0 ; } /* 책을 검색하는 함수 */ int search_book ( char ( * book_name)[ 30 ], char ( * auth_name)[ 30 ], char ( * publ_name)[ 30 ], int num_total_book) { int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; printf ( “어느 것으로 검색 할 것인가요?
” ); printf ( “1. 책 제목 검색
” ); printf ( “2. 지은이 검색
” ); printf ( “3. 출판사 검색
” ); scanf ( “%d” , & user_input); printf ( “검색할 단어를 입력해주세요 : ” ); scanf ( “%s” , user_search); printf ( “검색 결과
” ); if (user_input == 1 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 책 제목을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (book_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 2 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 지은이 이름을 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (auth_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } else if (user_input == 3 ) { /* i 가 0 부터 num_total_book 까지 가면서 각각의 출판사를 사용자가 입력한 검색어와 비교하고 있다. */ for (i = 0 ; i < num_total_book; i ++ ) { if ( compare (publ_name[i], user_search)) { printf ( "번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
" , i, book_name[i], auth_name[i], publ_name[i]); } } } return 0 ; } int compare ( char * str1, char * str2) { while ( * str1) { if ( * str1 != * str2) { return 0 ; } str1 ++ ; str2 ++ ; } if ( * str2 == '\0' ) return 1 ; return 0 ; } int borrow_book ( int * borrowed) { /* 사용자로 부터 책번호를 받을 변수*/ int book_num; printf ( "빌릴 책의 번호를 말해주세요
" ); printf ( "책 번호 : " ); scanf ( "%d" , & book_num); if (borrowed[book_num] == 1 ) { printf ( "이미 대출된 책입니다!
" ); } else { printf ( "책이 성공적으로 대출되었습니다.
" ); borrowed[book_num] = 1 ; } return 0 ; } int return_book ( int * borrowed) { /* 반납할 책의 번호 */ int num_book; printf ( "반납할 책의 번호를 써주세요
" ); printf ( "책 번호 : " ); scanf ( "%d" , & num_book); if (borrowed[num_book] == 0 ) { printf ( "이미 반납되어 있는 상태입니다
" ); } else { borrowed[num_book] = 0 ; printf ( "성공적으로 반납되었습니다
" ); } return 0 ; }
성공적으로 컴파일 했다면
실행 결과
도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 3 빌릴 책의 번호를 말해주세요 책 번호 : 0 책이 성공적으로 대출되었습니다. 도서 관리 프로그램 메뉴를 선택하세요 1. 책을 새로 추가하기 2. 책을 검색하기 3. 책을 빌리기 4. 책을 반납하기 5. 프로그램 종료 당신의 선택은 : 4 반납할 책의 번호를 써주세요 책 번호 : 0 성공적으로 반납되었습니다
위와 같이 아주 잘 작동됨을 알 수 있습니다.
아. 그럼 마침내 우리는 도서 관리 프로그램을 완성하였습니다!! 처음에 막연하게 도서 관리 프로그램을 만들라고 하니까 상당히 막연해 보였는데 하나 하나 조금씩 해보니 금새 만들게 되었습니다. 뿐만 아니라 함수를 이용해서 소스 코드의 가독성도 높여주었습니다.
뿐만 아니라 여러분이 도서 관리 프로그램을 만들면서 느끼게 될 점은 주석의 유용함 일 것입니다. 만일 우리가 주석 하나 없이 단순하게 프로그램을 만들었다면 나중에.. 한 1 달 뒤에 이 소스 코드를 다시 보게 된다면 "이 변수가 뭐지? 이 부분은 뭐하는 것이지?" 라는 생각이 들 것입니다. 저는 심지어 주석이 없이 프로그래밍 한 경우 어제 한 코드도 이해 못하는 경우가 있었습니다. 하지만 주석이 있다면 정말 아무리 오래 전에 만든 프로그램이여도 소스를 보면서 손쉽게 이해해 나갈 수 있습니다.
그럼 여기서 이번 강좌를 마치도록 하겠습니다.
생각해보기
문제 1
위 프로그램을 다 지우고 다시 만들어보자. 물론 소스가 정확히 일치하지 않아도 된다. 기능만 동일하면 된다. (난이도 : 下)
문제 2
search_book 함수는 살짝 지저분한 편이다. 다른 함수를 제작하여 조금 간추릴 수 있겠는가? (난이도 : 中下)
문제 3
search_book 함수를 조금 개량하여 빌려진 책은 검색결과 출력되지 않게 하거나, "대출됨" 이라는 문구가 출력되게 해보자. (난이도 : 下)
문제 4
search_book 함수를 개량하여 특정한 검색어를 입력했을 때 그 검색어를 포함하는 문자열도 검색되게 해보자. (난이도 : 中)
예를 들어 책 제목이 "learnCfast", "learningC", "whatisC?" 일 때, learn 를 검색하면 "learnCfast" 와 "learningC" 가 나온다. 왜냐하면 이들은 모두 "learn 라는 문자열을 포함하고 있기 때문이다.
C언어의 기초 개념들이 들어 있는 프로젝트, 도서 관리 프로젝트이다. 최종적으로 이러한 것을 만들 것이다.
콜솔이라 다소 조잡해 보이지만, 중요한 것은 내용이다!! API는 다 까먹었다!!! (충!성!)
내가 직접 도서관을 만든다고 생각하면서 차근차근 해야 할 것들을 생각해 보자. 우선 도서관에 있는 책들을 전산에 쓸 수 있도록 문서화해야 한다. 이것이 1번, 책을 새로 추가하기이다. 책들의 정보를 하나하나 추가해 주면서 총 몇권이 있는지도 확인해 주어야 할 것이다.
다음, 도서관에는 책들이 많다. 그래서 검색을 할 수가 있어야 한다. 검색을 하는 옵션으로는
1. 책 이름으로 검색
2. 저자로 검색
3. 출팔사로 검색
등을 생각해 볼 수 있을 것이다.
검색을 했다면, 책을 빌리고 반납할 수 있는 기능이 있어야 할 것이다. 이것이 3, 4번 내용이다.
다음으로, 이건 파일 입출력의 개념을 익히기 위해서 추가된 항목들인데, 책들의 내용을 txt파일로 출력하고, 반대로 이미 출력된 txt파일에서 책 리스트들을 불러올 수 있는 기능들을 추가할 것이다. 이렇게 말이다.
실컷 책들이름, 저자, 출판사, 대여 가능 여부들을 작성하고 5번을 누르면 아래와 같이 txt파일로 작성이 되게 할 것이다.
그리고 이렇게 작성된 파일을 불러와서 다시 사용할 수 있게 하는 것이 목표이다.
6번으로 리스트를 불러오고 7번으로 출력을 한 상황이다. 우선 가장 기본이 되는 책의 구조를 잡아보자.
1 2 3 4 5 6 typedef struct BOOK { char book_name[ 30 ]; char auth_name[ 30 ]; char publ_name[ 30 ]; int borrowed; }BOOK; cs
이렇게 구조체로 구조(?!!)를 잡아주었다. 보통 struct BOOK ㅇㅇㅇ 이렇게 쓰기 싫어서 typedef를 붙여주는 경우가 가 많다. 그런 다음, 이 책들의 배열인 도서관을 선언할 것이다.
1 2 3 4 5 6 7 8 9 int user_choice; /* 유저가 선택한 메뉴 */ int num_total_book = 0 ; /* 현재 책의 수 */ BOOK * book_list; printf ( “도서관의 최대 보관 장서 수를 설정해주세요 : ” ); scanf_s( “%d” , & user_choice); book_list = (BOOK * ) malloc ( sizeof (BOOK) * user_choice); cs
이는 사용자가 초기에 최대 권수를 설정할 수 있도록 동적 프로그래밍을 사용하였다. 그럼 이제, 각 기능들에 해당하는 함수들을 선언할 것이다.
1 2 3 4 5 6 7 char search_str( char * dic, char * word); int register_book(BOOK * book_list, int * nth); int search_book(BOOK * book_list, int total_num_book); int borrow_book(BOOK * book_list); int return_book(BOOK * book_list); int print_book_list(BOOK * book_list, int total_num_book); int retrieve_book_info(BOOK * * book_list, int * total_num_book); cs
각 함수들은, 책을 새로 추가하기, 책을 검색하기, 책을 빌리기/반납하기, 책들의 내용을 출력, 책들의 내용을 불러오는 기능들을 하는 함수들이다. 하나씩 만들어 보자. 그리고 함수들을 만들면서 어떠한 값들을 input으로 받아야 할지 생각을 해야 한다. 기본적으로 BOOK들의 리스트를 받고, 반복을 얼마나 해야 할 지 알기 위해서 전체 책이 몇 권이 있는지를 받기로 하였다. 제일 쉬운 책 추가부터 해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int register_book(BOOK * book_list, int * nth) { printf ( “책의 이름 : ” ); scanf_s( “%s” , book_list[ * nth].book_name, sizeof (book_list[ * nth].book_name)); printf ( “책의 저자 : ” ); scanf_s( “%s” , book_list[ * nth].auth_name, sizeof (book_list[ * nth].auth_name)); printf ( “책의 출판사 : ” ); scanf_s( “%s” , book_list[ * nth].publ_name, sizeof (book_list[ * nth].publ_name)); book_list[ * nth].borrowed = 0 ; ( * nth) + + ; return 0 ; } Colored by Color Scripter cs
그냥 scanf로 모두 받은 다음, 전체 권수를 추가만 해 주면 될 것이다. 다음은, 책 검색.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 int search_book(BOOK * book_list, int total_num_book) { int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; printf ( “어느 것으로 검색 할 것인가요?
” ); printf ( “1. 책 제목 검색
” ); printf ( “2. 지은이 검색
” ); printf ( “3. 출판사 검색
” ); scanf_s( “%d” , & user_input); printf ( “검색할 단어를 입력해주세요 : ” ); scanf_s( “%s” , user_search, sizeof (user_search)); printf ( “검색 결과
” ); if (user_input = = 1 ) { for (i = 0 ; i < total_num_book; i + + ) { if (search_str(book_list[i].book_name, user_search) > = 0 ) { printf ( “번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
” , i, book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); } else printf ( “그런 책 없음.
” ); } } else if (user_input = = 2 ) { for (i = 0 ; i < total_num_book; i + + ) { if (search_str(book_list[i].auth_name, user_search) > = 0 ) { printf ( “번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
” , i, book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); } else printf ( “그런 책 없음.
” ); } } else if (user_input = = 3 ) { for (i = 0 ; i < total_num_book; i + + ) { if (search_str(book_list[i].publ_name, user_search) > = 0 ) { printf ( “번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
” , i, book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); } else printf ( “그런 책 없음.
” ); } } return 0 ; } Colored by Color Scripter cs
어떤 정보로 검색을 할 지 결정하고, search_str로 실질적인 검색을 한다. search_str은 그냥 문자열을 검색하는 함수이고, 간단하게 그 문자열이 있는지만 보는 함수이다. 아래와 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 char search_str( char * dic, char * word) { int loc = 0 ; int search_loc = 0 ; while ( * dic) { if ( * dic = = * word) { while ( * word) { if ( * dic ! = * word) { word – = search_loc; loc + = search_loc; search_loc = 0 ; break ; } dic + + ; word + + ; search_loc + + ; if ( * word = = 0 ) { return loc; } } } dic + + ; loc + + ; } return – 1 ; } Colored by Color Scripter cs
책을 빌리고 반납하는 것은 매우 쉽다. borrowed 변수가 0이면 대출 가능한 것, 1이면 이미 대출된 것이라 하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 int borrow_book(BOOK * book_list) { /* 사용자로 부터 책번호를 받을 변수*/ int book_num; printf ( “빌릴 책의 번호를 말해주세요
” ); printf ( “책 번호 : ” ); scanf_s( “%d” , & book_num); if (book_list[book_num].borrowed = = 1 ) { printf ( “이미 대출된 책입니다!
” ); } else { printf ( “책이 성공적으로 대출되었습니다.
” ); book_list[book_num].borrowed = 1 ; } return 0 ; } int return_book(BOOK * book_list) { /* 반납할 책의 번호 */ int num_book; printf ( “반납할 책의 번호를 써주세요
” ); printf ( “책 번호 : ” ); scanf_s( “%d” , & num_book); if (book_list[num_book].borrowed = = 0 ) { printf ( “이미 반납되어 있는 상태입니다
” ); } else { book_list[num_book].borrowed = 0 ; printf ( “성공적으로 반납되었습니다
” ); } return 0 ; } Colored by Color Scripter cs
이제 책의 리스트를 파일 입출력을 이용해 메모장에 기록하는 함수를 만들 것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 int print_book_list(BOOK * book_list, int total_num_book) { FILE * fp; errno_t err = fopen_s( & fp, “book_list.txt” , “w” ); if (err = = 0 ) { printf ( “success!! ” ); } else { printf ( “error” ); return 0 ; } fprintf(fp, “%d
” , total_num_book); for ( int i = 0 ; i < total_num_book; i + + ) { fprintf(fp, "%s
%s
%s
" , book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); if (book_list[i].borrowed = = 0 ) fprintf(fp, "NO
" ); else fprintf(fp, "YES
" ); } fclose(fp); return 0 ; } Colored by Color Scripter cs
파일 입출력을 위해서 stdlib.h는 미리 include한 상태이다.
마지막으로 이미 만들어진 메모장 파일을 불러오는 기능을 만들었다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 int retrieve_book_info(BOOK * * book_list, int * total_num_book) { FILE * fp; errno_t err = fopen_s( & fp, "book_list.txt" , "r" ); int total_book; char borrow[ 10 ]; if (err = = 0 ) { printf ( "success!! " ); } else { printf ( "error" ); return 0 ; } fscanf_s(fp, "%d" , & total_book); * total_num_book = total_book; free ( * book_list); ( * book_list) = (BOOK * ) malloc ( sizeof (BOOK) * total_book); ; for ( int i = 0 ; i < total_book; i + + ) { fscanf_s(fp, "%s" , ( * book_list)[i].book_name, sizeof (( * book_list)[i].book_name)); fscanf_s(fp, "%s" , ( * book_list)[i].auth_name, sizeof (( * book_list)[i].auth_name)); fscanf_s(fp, "%s" , ( * book_list)[i].publ_name, sizeof (( * book_list)[i].publ_name)); fscanf_s(fp, "%s" , borrow, sizeof (borrow)); //printf("%s %s %s %s
", (*book_list)[i].book_name, (*book_list)[i].auth_name, (*book_list)[i].publ_name, borrow); //printf("%d
", strcmp(borrow, "NO")); if (strcmp(borrow, "NO" ) = = 0 ) ( * book_list)[i].borrowed = 0 ; else if (strcmp(borrow, "YES" ) = = 0 ) ( * book_list)[i].borrowed = 1 ; //printf("%d", (book_list[i])->borrowed); } return 0 ; } Colored by Color Scripter cs
여기에서 혼동이 올 수가 있는데 아래의 접근 방식이다.
(*book_list)[i].book_name
book_list는 BOOK들이 들어 있는 구조체 리스트이다. 그래서 아래와 같이 써 주면 book_list는 하나밖에 없는데 다음 book_list에 접근하려고 하기 때문에 작동이 되질 않는다. (참고로 이렇게 실수를 해도 어떠한 오류도 검출되지 않는다.) 아래의 풀이를 보면 이해가 될 것이다 .
(*book_list)[i].book_name == ( *( *book_list + i)).book_name
book_list[i]->book_name == ( *( *(book_list + i))).book_name
그럼, 전체 코드는 다음과 같아질 것이다. 아래 글자를 누르면 펼쳐진다.
더보기
접기
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 #include < stdio.h > #include < stdlib.h > #include < string .h > typedef struct BOOK { char book_name[ 30 ]; char auth_name[ 30 ]; char publ_name[ 30 ]; int borrowed; }BOOK; char search_str( char * dic, char * word); int register_book(BOOK * book_list, int * nth); int search_book(BOOK * book_list, int total_num_book); int borrow_book(BOOK * book_list); int return_book(BOOK * book_list); int print_book_list(BOOK * book_list, int total_num_book); int retrieve_book_info(BOOK * * book_list, int * total_num_book); int main() { int user_choice; /* 유저가 선택한 메뉴 */ int num_total_book = 0 ; /* 현재 책의 수 */ BOOK * book_list; printf ( “도서관의 최대 보관 장서 수를 설정해주세요 : ” ); scanf_s( “%d” , & user_choice); book_list = (BOOK * ) malloc ( sizeof (BOOK) * user_choice); while ( 1 ) { printf ( “도서 관리 프로그램
” ); printf ( “메뉴를 선택하세요
” ); printf ( “1. 책을 새로 추가하기
” ); printf ( “2. 책을 검색하기
” ); printf ( “3. 책을 빌리기
” ); printf ( “4. 책을 반납하기
” ); printf ( “5. 책들의 내용을 book_list.txt 에 출력
” ); printf ( “6. 책들의 내용을 book_list.txt 에서 불러옴
” ); printf ( “7. 책들의 목록을 출력
” ); printf ( “8. 프로그램 종료
” ); printf ( “당신의 선택은 : ” ); scanf_s( “%d” , & user_choice); if (user_choice = = 1 ) { /* 책을 새로 추가하는 함수 호출 */ register_book(book_list, & num_total_book); } else if (user_choice = = 2 ) { /* 책을 검색하는 함수 호출 */ search_book(book_list, num_total_book); } else if (user_choice = = 3 ) { /* 책을 빌리는 함수 호출 */ borrow_book(book_list); } else if (user_choice = = 4 ) { /* 책을 반납하는 함수 호출 */ return_book(book_list); } else if (user_choice = = 5 ) { print_book_list(book_list, num_total_book); } else if (user_choice = = 6 ) { retrieve_book_info( & book_list, & num_total_book); } else if (user_choice = = 7 ) { for ( int i = 0 ; i < num_total_book; i + + ) { printf ( "%s // %s // %s // " , book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); if (book_list[i].borrowed = = 0 ) printf ( "NO
" ); else printf ( "YES
" ); } } else { printf ( "/* 프로그램을 종료. */" ); break ; } } free (book_list); return 0 ; } char search_str( char * dic, char * word) { int loc = 0 ; int search_loc = 0 ; while ( * dic) { if ( * dic = = * word) { while ( * word) { if ( * dic ! = * word) { word - = search_loc; loc + = search_loc; search_loc = 0 ; break ; } dic + + ; word + + ; search_loc + + ; if ( * word = = 0 ) { return loc; } } } dic + + ; loc + + ; } return - 1 ; } int register_book(BOOK * book_list, int * nth) { printf ( "책의 이름 : " ); scanf_s( "%s" , book_list[ * nth].book_name, sizeof (book_list[ * nth].book_name)); printf ( "책의 저자 : " ); scanf_s( "%s" , book_list[ * nth].auth_name, sizeof (book_list[ * nth].auth_name)); printf ( "책의 출판사 : " ); scanf_s( "%s" , book_list[ * nth].publ_name, sizeof (book_list[ * nth].publ_name)); book_list[ * nth].borrowed = 0 ; ( * nth) + + ; return 0 ; } int search_book(BOOK * book_list, int total_num_book) { int user_input; /* 사용자의 입력을 받는다. */ int i; char user_search[ 30 ]; printf ( "어느 것으로 검색 할 것인가요?
" ); printf ( "1. 책 제목 검색
" ); printf ( "2. 지은이 검색
" ); printf ( "3. 출판사 검색
" ); scanf_s( "%d" , & user_input); printf ( "검색할 단어를 입력해주세요 : " ); scanf_s( "%s" , user_search, sizeof (user_search)); printf ( "검색 결과
" ); if (user_input = = 1 ) { for (i = 0 ; i < total_num_book; i + + ) { if (search_str(book_list[i].book_name, user_search) > = 0 ) { printf ( “번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
” , i, book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); } else printf ( “그런 책 없음.
” ); } } else if (user_input = = 2 ) { for (i = 0 ; i < total_num_book; i + + ) { if (search_str(book_list[i].auth_name, user_search) > = 0 ) { printf ( “번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
” , i, book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); } else printf ( “그런 책 없음.
” ); } } else if (user_input = = 3 ) { for (i = 0 ; i < total_num_book; i + + ) { if (search_str(book_list[i].publ_name, user_search) > = 0 ) { printf ( “번호 : %d // 책 이름 : %s // 지은이 : %s // 출판사 : %s
” , i, book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); } else printf ( “그런 책 없음.
” ); } } return 0 ; } int borrow_book(BOOK * book_list) { /* 사용자로 부터 책번호를 받을 변수*/ int book_num; printf ( “빌릴 책의 번호를 말해주세요
” ); printf ( “책 번호 : ” ); scanf_s( “%d” , & book_num); if (book_list[book_num].borrowed = = 1 ) { printf ( “이미 대출된 책입니다!
” ); } else { printf ( “책이 성공적으로 대출되었습니다.
” ); book_list[book_num].borrowed = 1 ; } return 0 ; } int return_book(BOOK * book_list) { /* 반납할 책의 번호 */ int num_book; printf ( “반납할 책의 번호를 써주세요
” ); printf ( “책 번호 : ” ); scanf_s( “%d” , & num_book); if (book_list[num_book].borrowed = = 0 ) { printf ( “이미 반납되어 있는 상태입니다
” ); } else { book_list[num_book].borrowed = 0 ; printf ( “성공적으로 반납되었습니다
” ); } return 0 ; } int print_book_list(BOOK * book_list, int total_num_book) { FILE * fp; errno_t err = fopen_s( & fp, “book_list.txt” , “w” ); if (err = = 0 ) { printf ( “success!! ” ); } else { printf ( “error” ); return 0 ; } fprintf(fp, “%d
” , total_num_book); for ( int i = 0 ; i < total_num_book; i + + ) { fprintf(fp, "%s
%s
%s
" , book_list[i].book_name, book_list[i].auth_name, book_list[i].publ_name); if (book_list[i].borrowed = = 0 ) fprintf(fp, "NO
" ); else fprintf(fp, "YES
" ); } fclose(fp); return 0 ; } int retrieve_book_info(BOOK * * book_list, int * total_num_book) { FILE * fp; errno_t err = fopen_s( & fp, "book_list.txt" , "r" ); int total_book; char borrow[ 10 ]; if (err = = 0 ) { printf ( "success!! " ); } else { printf ( "error" ); return 0 ; } fscanf_s(fp, "%d" , & total_book); * total_num_book = total_book; free ( * book_list); ( * book_list) = (BOOK * ) malloc ( sizeof (BOOK) * total_book); ; for ( int i = 0 ; i < total_book; i + + ) { fscanf_s(fp, "%s" , ( * book_list)[i].book_name, sizeof (( * book_list)[i].book_name)); fscanf_s(fp, "%s" , ( * book_list)[i].auth_name, sizeof (( * book_list)[i].auth_name)); fscanf_s(fp, "%s" , ( * book_list)[i].publ_name, sizeof (( * book_list)[i].publ_name)); fscanf_s(fp, "%s" , borrow, sizeof (borrow)); //printf("%s %s %s %s
", (*book_list)[i].book_name, (*book_list)[i].auth_name, (*book_list)[i].publ_name, borrow); //printf("%d
", strcmp(borrow, "NO")); if (strcmp(borrow, "NO" ) = = 0 ) ( * book_list)[i].borrowed = 0 ; else if (strcmp(borrow, "YES" ) = = 0 ) ( * book_list)[i].borrowed = 1 ; //printf("%d", (book_list[i])->borrowed); } return 0 ; } Colored by Color Scripter cs
접기
아주 기초적인 프로그램이었다. 가끔 C를 까먹으면 다시 만들면서 복기할 생각이다.