문자열 - 도서 관리 프로젝트

CHOI·2021년 7월 12일
0

C 언어

목록 보기
19/28
post-thumbnail
int user_input; /* 사용자의 입력을 받는다. */
int i;
char user_search[30]; /* 사용자가 입력한 검색어 */
int add_book(char (*book_name)[30], char (*auth_name)[30],
             char (*publ_name)[30], int *borrowed, int *num_total_book);

기존에는 작은 프로그램들만 만들어 보았는데 이번에는 여러 작은 기능을 하는 프로그램을 묶어서 하나의 거대한 프로그램을 만드는 프로젝트를 해보자.

우리는 이제 도서 관리 프로그램을 만들어 볼 것이다. 우리가 도서관을 만든다고 했을 떄 그 도서관을 운영하는데 필요한 프로그램들을 만들어보는 것이다. 우리가 원하는 기능들은 다음과 같다.

  1. 책을 추가하는 기능(책의 총 개수는 100개라고 하고 각 책의 정보로는 제목, 저자, 출판사로 한다.)
  2. 책의 제목을 검색하면 그 책의 정보가 나와야 한다.
  3. 저자, 출판사도 마찬가지로 검색하면 그 책의 정보가 나와야 한다.
  4. 책을 빌리는 기능
  5. 책을 반납하는 기능

지금부터 프로그램을 만들어보자. 아래의 정답은 보지 말고 최소한 3개정도는 만들어보자. 만약 3개를 못 만들었다? 그러면 이 강의를 닫고 다시 시도해보자

프로그램을 어떻게 만들 것인가?

이렇게 거대한(?) 프로그램을 만들때는 작은 프로그램을 만들때와 다르게 체계적으로 계획을 세우는 것이 중요하다. 이 떄, 체계적으로 계획을 세운다는건 다음을 모두 생각해 보는 것이다.

  1. 이 프로그램은 무슨 작업을 하는 것인가?
  2. 과연 이 작업이 꼭 필요한 것인가? (그렇지 않다면 1번으로)
  3. 어떠한 환경에서 프로그램이 작동하는가?
  4. 어떠한 언어로 개발을 할 것인가?

우선 1 번의 경우는 프로그램을 계획하는 단계에서 가장 중요한 단계이다.

우리가 만들 프로그램은 '도서 관리 프로그램'이다. 이 프로그램에서는 도서를 관리하는데 꼭 필요한 기능만 들어가야 한다. 예를 들어서 위에서 말했던 기능들 말이다. 만약 쓸데 없는 작업을 많이 넣게 된다면 프로그램의 용량도 커질 뿐더러 개발하는데 시간도 많이 소요되기 때문이다.

2 번의 경우 1 번에서 내가 한 것들을 다시 확인하는 단계이다. 필요 없는 기능이나 꼭 필요하지 않거나 혹은 프로그램의 목적과 부합하지 않는 작업들의 경우 다시 1번으로 돌아가 생각해 보아야 할 필요성이 있다.

3 번의 경우 우리에게는 큰 문제는 아니지만 실제로 프로그램을 개발하게 되면 매우 중요한 역할을 하게 된다. 우리가 만든 프로그램이 Windows에서 작동 될 수 있고 Linux 나 MacOS에서 작동될 수도 있다. 또한 스마트폰이나 사물인터넷에서 사용될 수 있다. 각 환경에 맞는 프로그램이 다르다. ATM기기나 은행 쪽에서는 속도가 조금 느리더라도 보안이 우선이 되어야 하고 스마트폰은 보통 PC에 비해 사양이 낮기 때문에 더 가볍게 돌아가야 하는 등 각 환경에 맞게 프로그램을 개발해야 한다.

4 번의 경우 지금 우리는 C 이지만 각 프로그래밍 언어마다 특성이 있기 때문에 1,2,3을 전부 고려하여 상황에 맞는 프로그래밍 언어를 사용해야 한다.

프로그램 뼈대 만들기

우리는 단순히 개발 실력을 늘리기 위한 것이기 때문에 화면을 이쁘게 만들 필요가 없다. 따라서 이 도서 관리 프로그램은 단순하게 처음에 메뉴를 입력받고 입력 받은 일을 수행하고 나서 다시 메뉴로 돌아오도록 하면 좋을 것 같다.

따라서 기본 뼈대를 다음과 같이 만들었다.(물론 각자 만든 뼈대가 더 좋은 것일 수 있다.)

#include <stdio.h>
int main() {
  int user_choice; /* 유저가 선택한 메뉴*/

  while (1) {
    printf("도서 관리 프로그램 \n");
    printf("메뉴를 선택하세요 \n");
    printf("1. 책을 새로 추가하기 \n");
    printf("2. 책을 검색하기 \n");
    printf("3. 책을 빌리기 \n");
    printf("4. 책을 반납하기 \n");
    printf("5. 프로그램 종료 \n");

    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;
}

위 소스 코드에 대해서 조금만 설명하자면 while(1) 이기 때문에 항상 '참'이 되어 반복문이 계속 반복된다. 그러다가 5 번을 입력하면 break 가 실행되어 반복문이 종료되고 프로그램이 종료가 되는 방식이다.

이 프로그램에서 필요한 변수는?

기본적으로 책의 제목, 저자, 출판사를 저장할 배열이 필요한 것을 느낄 수 있다. 그리고 또한 현재 책이 빌릴 수 있는지 또는 빌릴 수 없는지 표시해줄 배열도 필요하다. 마지막으로 현재 총 책의 개수가 있어야 나중에 책을 추가할 때 배열의 몇 번째 원소에 추가해줄지 알 수 있다. 따라서 이들을 조합하면 다음과 같이 선언할 수 있다.

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이면 '빌리지 않음' 으로 생각하면 된다.

책을 추가하는 함수

이제 함수를 만들어보자. 먼저 책을 추가하는 함수를 만들어보자. 이름은 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 언어는 위 인자들이 같은 문장에 나열되어 있다고 생각하기 때문이다. 따라서 인자가 길어서 보기 흉하면 엔터를 쳐서 깔끔하게 만들어도 된다.

아무튼 함수를 완성해보면 다음과 같다.

/* 책을 추가하는 함수*/
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("추가 완료! \n");
  (*num_total_book)++;

  return

이렇게 함수를 정의하고 main 함수에 추가하면 다음과 같다.

#include <stdio.h>
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("도서 관리 프로그램 \n");
    printf("메뉴를 선택하세요 \n");
    printf("1. 책을 새로 추가하기 \n");
    printf("2. 책을 검색하기 \n");
    printf("3. 책을 빌리기 \n");
    printf("4. 책을 반납하기 \n");
    printf("5. 프로그램 종료 \n");

    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("추가 완료! \n");
  (*num_total_book)++;

  return 0;
}

이와 같다. 여기까지 이해하는데 큰 무리가 없을 것이다. 그런데 여기서 주의해야 할 부분이 있는데 다음과 같다.

add_book(book_name, auth_name, publ_name, borrowed, &num_total_book);

위와 같이 & 주소 연산자를 어디에 붙일지 매우 헷갈린다는 것이다. 기본적으로 배열의 경우 배열의 이름이 배열의 주소값을 나타내기 때문에 주소 연산자를 사용할 필요가 없지만(정확히 말하면 안된다.) 그러나 num_total_book 과 같은 int 형 변수 같은 경우 int * 포인터에 주소값을 전달하기 위해선 & 인 주소 연산자를 사용하여 num_total_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("어느 것으로 검색 할 것인가요? \n");
  printf("1. 책 제목 검색 \n");
  printf("2. 지은이 검색 \n");
  printf("3. 출판사 검색 \n");
  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("어느 것으로 검색 할 것인가요? \n");
  printf("1. 책 제목 검색 \n");
  printf("2. 지은이 검색 \n");
  printf("3. 출판사 검색 \n");
  scanf("%d", &user_input);

  printf("검색할 단어를 입력해주세요 : ");
  scanf("%s", user_search);

  printf("검색 결과 \n");

  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 \n", 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 \n", 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 \n", i,
               book_name[i], auth_name[i], publ_name[i]);
      }
    }
  }

  return 0;
}

길어서 당황할 수 있지만 사실 살펴보면 매우 간단하다. 위의 소스 코드만 읽어보아도 쉽게 이해할 수 있을 것이다.

이제 이를 main 함수에 적용하여 완성된 코드는 다음과 같다.

#include <stdio.h>
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("도서 관리 프로그램 \n");
    printf("메뉴를 선택하세요 \n");
    printf("1. 책을 새로 추가하기 \n");
    printf("2. 책을 검색하기 \n");
    printf("3. 책을 빌리기 \n");
    printf("4. 책을 반납하기 \n");
    printf("5. 프로그램 종료 \n");

    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("추가 완료! \n");
  (*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("어느 것으로 검색 할 것인가요? \n");
  printf("1. 책 제목 검색 \n");
  printf("2. 지은이 검색 \n");
  printf("3. 출판사 검색 \n");
  scanf("%d", &user_input);

  printf("검색할 단어를 입력해주세요 : ");
  scanf("%s", user_search);

  printf("검색 결과 \n");

  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 \n", 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 \n", 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 \n", 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;
}

빌리는 함수 / 반납하는 함수

우선 빌리는 함수를 만들어보자 함수의 이름은 borrow_book 로 하자.

int borrow_book(int *borrowed) {
  /* 사용자로 부터 책번호를 받을 변수*/
  int book_num;

  printf("빌릴 책의 번호를 말해주세요 \n");
  printf("책 번호 : ");
  scanf("%d", &book_num);

  if (borrowed[book_num] == 1) {
    printf("이미 대출된 책입니다! \n");
  } else {
    printf("책이 성공적으로 대출되었습니다. \n");
    borrowed[book_num] = 1;
  }

  return 0;
}

사실 이 함수는 매우 간단하다. 다만 주의할 점은 이미 1 이라면 이미 대출된 책입니다! 라고 출력해주고 아니라면 책이 성공적으로 대출되었습니다. 라고 출력하고 0 에서 1 로 바꿔줘야 한다는 것이다.

마찬가지 아이디어로 반납하는 함수를 만들어보면 이름을 return_book 로 하자. 앞서 책을 빌리는 함수와 하는일이 거의 똑같으니까 설명은 생략하겠다.

int return_book(int *borrowed) {
  /* 반납할 책의 번호 */
  int num_book;

  printf("반납할 책의 번호를 써주세요 \n");
  printf("책 번호 : ");
  scanf("%d", &num_book);

  if (borrowed[num_book] == 0) {
    printf("이미 반납되어 있는 상태입니다\n");
  } else {
    borrowed[num_book] = 0;
    printf("성공적으로 반납되었습니다\n");
  }

  return 0;
}

이제 이 두 함수를 main 에 추가하면

#include <stdio.h>
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("도서 관리 프로그램 \n");
    printf("메뉴를 선택하세요 \n");
    printf("1. 책을 새로 추가하기 \n");
    printf("2. 책을 검색하기 \n");
    printf("3. 책을 빌리기 \n");
    printf("4. 책을 반납하기 \n");
    printf("5. 프로그램 종료 \n");

    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("추가 완료! \n");
  (*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("어느 것으로 검색 할 것인가요? \n");
  printf("1. 책 제목 검색 \n");
  printf("2. 지은이 검색 \n");
  printf("3. 출판사 검색 \n");
  scanf("%d", &user_input);

  printf("검색할 단어를 입력해주세요 : ");
  scanf("%s", user_search);

  printf("검색 결과 \n");

  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 \n", 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 \n", 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 \n", 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("빌릴 책의 번호를 말해주세요 \n");
  printf("책 번호 : ");
  scanf("%d", &book_num);

  if (borrowed[book_num] == 1) {
    printf("이미 대출된 책입니다! \n");
  } else {
    printf("책이 성공적으로 대출되었습니다. \n");
    borrowed[book_num] = 1;
  }

  return 0;
}
int return_book(int *borrowed) {
  /* 반납할 책의 번호 */
  int num_book;

  printf("반납할 책의 번호를 써주세요 \n");
  printf("책 번호 : ");
  scanf("%d", &num_book);

  if (borrowed[num_book] == 0) {
    printf("이미 반납되어 있는 상태입니다\n");
  } else {
    borrowed[num_book] = 0;
    printf("성공적으로 반납되었습니다\n");
  }

  return 0;
}

이와 같다.

그러면 이제 우리가 원했던 도서 관리 프로그램이 만들어졌다. 막연하게 프로그램을 만들려고 했을 때는 어려워 보였는데 막상 하나하나 하다보니까 금세 만들었다. 그리고 생각보다 매우 간단하였다. 뿐만 아니라 함수를 이용하여 가독성도 높여주었다.

이 프로그램을 만들면서 느끼게 되었을 점들은 주석의 유용함일 것이다. 우리가 만약에 주석을 하나도 사용하지 않고 그냥 프로그램을 만들었다면 다른 사람은 물론이고 스스로 만든 내가 1달 정도 뒤에 보아도 이 변수는 무슨 일을 하고 이 함수는 무슨일을 하는지 잘 알지 못할 것이다. 하지만 주석을 이용하면 아무리 오래전에 만든 프로그램일지라도 소스를 보면서 손쉽게 이해할 수 있을 것이다.

참고로 위의 소스 코드들은 전부 씹어먹는 C 언어에서 소개하는 예제들이다. 필자가 직접 작성한 코드는 다음과 같다.

#include <stdio.h>
int add(char (*book_name)[30], char (*book_writer)[30], char (*book_publisher)[30], int *total_book_num);
int compare(char *str1, char *str2);
int search (char (*book_name)[30], char (*book_writer)[30], char (*book_publisher)[30], int *total_book_num);
int borrow (char *book_status);
int book_return (char *book_status);

int main(){
    char book_name[100][30] ,book_writer[100][30],book_publisher[100][30], book_status[100]={0};
    
    
    int add(char (*book_name)[30], char (*book_writer)[30], char (*book_publisher)[30], int *total_book_num);
    int total_book_num=0, user_choice;
    
    printf("-------------------------------\n");
    printf("안녕하세요 도서 관리 프로그램입니다.\n\n");
    printf("1. 책 추가하기 \n");
    printf("2. 책 검색하기 \n");
    printf("3. 책 빌리기 \n");
    printf("4. 책 반납하기 \n");
    printf("5. 프로그램 종료하기 \n");
    
    
    while (1){
        printf("-------------------------------\n");
        printf("어떤 일을 도와드릴까요?\n번호를 입력해주세요 :");

        scanf("%d",&user_choice);
        
        if (user_choice==1){
            /* 책 추가하는 함수*/
            add(book_name, book_writer, book_publisher, &total_book_num);
        }else if (user_choice==2){
            /* 책 검색하는 함수*/
            search(book_name, book_writer, book_publisher, &total_book_num);
        }else if (user_choice==3){
            /* 책 빌리는 함수*/
            borrow(book_status);
        }else if (user_choice==4){
            /* 책 반납하는 함수*/
            book_return(book_status);
        }else if (user_choice==5){
            /* 프로그램 종료 */
            break;
        }else{
            printf("번호를 잘못 입력하였습니다.\n");
        }
    }
    
    return 0;
}

/* 책 추가하는 함수*/
int add(char (*book_name)[30], char (*book_writer)[30], char (*book_publisher)[30], int *total_book_num){
    
    printf("책의 이름 :");
    scanf("%s",book_name[*total_book_num]);
    
    printf("책의 저자 :");
    scanf("%s",book_writer[*total_book_num]);
    
    printf("책의 출판사 :");
    scanf("%s",book_publisher[*total_book_num]);
    
    (*total_book_num)++; // 전체 책의 개수에 1 더하기
    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 search (char (*book_name)[30], char (*book_writer)[30], char (*book_publisher)[30], int *total_book_num){
    int user_choice, book_num=0,check=1;
    char contents[30]; // 검색할 내용
    printf("어떤 것을 가지고 검색하실 건가요?\n");
    printf("1. 책 이름\n");
    printf("2. 책 저자\n");
    printf("3. 책 출판사\n");
    printf("입력 :");
    scanf("%d",&user_choice);
    
    printf("검색할 내용을 입력하세요. :");
    scanf("%s",contents);
    
    if (user_choice == 1){
        while (book_num < *total_book_num){
            if (compare(contents, book_name[book_num])){
                printf("책 번호 : %d\n",book_num);
                printf("책 제목 : %s\n",book_name[book_num]);
                printf("책 저자 : %s\n",book_writer[book_num]);
                printf("책 출판사 : %s\n",book_publisher[book_num]);
                printf("더 찾으려면 1번을, 끝내려면 0을 입력하세요. : ");
                scanf("%d",&check);
                /* 계속 찾으려면 check 는 1 아니면 0 */
                if (check == 0) break;
            }
            book_num++;
        }
        if (check == 1) printf("검색 결과 없습니다.\n");
        
    }else if (user_choice == 2){
        while (book_num < *total_book_num){
            if (compare(contents, book_writer[book_num])){
                printf("책 번호 : %d\n",book_num);
                printf("책 제목 : %s\n",book_name[book_num]);
                printf("책 저자 : %s\n",book_writer[book_num]);
                printf("책 출판사 : %s\n",book_publisher[book_num]);
                /* 계속 찾으려면 check 는 1 아니면 0 */
                if (check == 0) break;
            }
            book_num++;
        }
        if (check == 1) printf("검색 결과 없습니다.\n");
       

    }else if (user_choice == 3){
        while (book_num < *total_book_num){
            if (compare(contents, book_publisher[book_num])){
                printf("책 번호 : %d\n",book_num);
                printf("책 제목 : %s\n",book_name[book_num]);
                printf("책 저자 : %s\n",book_writer[book_num]);
                printf("책 출판사 : %s\n",book_publisher[book_num]);
                /* 계속 찾으려면 check 는 1 아니면 0 */
                if (check == 0) break;
            }
            book_num++;
        }
        if (check == 1) printf("검색 결과 없습니다.\n");
    }
    
    return 0;
}
/* 책 빌리는 함수 */
int borrow (char *book_status){
    int book_num;
    printf("빌릴 책 번호를 입력해주세요. : ");
    scanf("%d",&book_num);
    
    if (book_status[book_num] == 1){
        printf("이 책은 대출중입니다.\n");
    } else{
        book_status[book_num] = 1;
        printf("책을 대출 하였습니다.\n");
        
    }
    return 0;
}

/* 책 반납 함수 */
int book_return (char *book_status){
    int book_num;
    printf("반납할 책 번호를 입력해주세요. : ");
    scanf("%d",&book_num);
    
    if (book_status[book_num] == 0){
        printf("이 책은 이미 반납했습니다.\n");
    } else{
        book_status[book_num] = 0;
        printf("책을 반납 하였습니다.\n");
        
    }
    return 0;
}
profile
벨로그보단 티스토리를 사용합니다! https://flight-developer-stroy.tistory.com/

0개의 댓글