[4번 과제] C++ Summary

정채은·2025년 6월 17일

C++ 프로그래밍

목록 보기
11/16

✅ 필수 기능 가이드

기존 도서관 관리 프로그램에 검색 기능을 추가해주세요

  • 책 제목으로 검색이 가능해야 합니다.
  • 작가로 검색이 가능해야 합니다.
  • 책 제목이 동일한 경우는 없다고 가정 합니다.

필수 기능 구현 완료 후 전체적인 구조를 그리면 아래와 같습니다.

어디까지나 참조일 뿐 꼭 이대로 구현할 필요는 없습니다.

🔥 도전 기능 가이드

기존 도서관 관리 프로그램에 필수 기능을 추가한 상태에서 아래 대여 기능을 추가해주세요

  • 특정 책의 대여 여부를 알 수 있어야 합니다.
  • 책의 이름으로 대여 여부를 검색하고 대여가 아닌 경우 대여할 수 있어야 합니다.
  • 책의 작가로 대여 여부를 검색하고 대여가 아닌 경우 대여할 수 있어야 합니다.
  • 책을 반납할 수 있어야 합니다.
  • 모든 책의 재고는 난이도를 낮추기 위해 3권으로 통일 합니다.

도전 기능 구현까지 완료한 후 전체적인 구조를 그리면 아래와 같습니다.

어디까지나 참조일 뿐 꼭 이대로 구현할 필요는 없습니다.

내가 짠 코드

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <unordered_map>

using namespace std; // namespace std 사용

class Book {
public:
    string title;
    string author;

    Book(const string& title, const string& author)
        : title(title), author(author) {
    }
};

class BookManager {
private:
    vector<Book> books; // 책 목록 저장

public:
    // 책 추가 메서드
    void addBook(const string& title, const string& author) {
        books.push_back(Book(title, author)); // push_back 사용
        cout << "책이 추가되었습니다: " << title << " by " << author << endl;
    }


    // 모든 책 출력 메서드
    void displayAllBooks() const {
        if (books.empty()) {
            cout << "현재 등록된 책이 없습니다." << endl;
            return;
        }

        cout << "현재 도서 목록:" << endl;
        for (size_t i = 0; i < books.size(); i++) { // 일반적인 for문 사용
            cout << "- " << books[i].title << " by " << books[i].author << endl;
        }
    }

    // 책 제목 검색
    void searchByTitle(const string& title) {
        bool isFind = false;
        for (size_t i = 0; i < books.size(); i++) {
            if (books[i].title == title) {
                cout << "찾은 책 : " << books[i].title << " by " << books[i].author << endl;
                isFind = true;
            }
        }
        if (!isFind) cout << "검색한 책이 존재하지 않습니다." << endl;
    }

    // 작가 검색
    void searchByAuthor(const string& author) {
        bool isFind = false;
        for (size_t i = 0; i < books.size(); i++) {
            if (books[i].author == author) {
                cout << "찾은 책 : " << books[i].title << " by " << books[i].author << endl;
                isFind = true;
            }
        }
        if(!isFind) cout << "검색한 작가가 존재하지 않습니다." << endl;
    }


    const vector<Book>& getBooks() const {
        return books;
    }

    // 마지막에 들어온 책 == 방금 들어온 책 반환
    const Book& getLastBooks() const {

        return books.back();
    }

};


class BorrowManager {
private:
    unordered_map<string, int> stock; // 책 제목 -> 재고 수량

public:
    // 초기화 (Book 목록 받아서 재고 3으로 설정)
    void initializeStock(const Book& book, int quantity = 3) {
        stock[book.title] = quantity;
    }

    // 제목으로 대여
    void borrowBookByTitle(const vector<Book>& books, const string& title) {
        for (const auto& book : books) {
            if (book.title == title) {
                if (stock[title] > 0) {
                    stock[title]--;
                    cout << "[" << title << "] 책을 대여했습니다. 남은 재고: " << stock[title] << endl;
                }
                else {
                    cout << "[" << title << "] 책은 현재 모두 대여 중입니다." << endl;
                }
                return;
            }
        }
        cout << title << "' 에 해당하는 책이 없습니다." << endl;
    }

    // 작가로 대여
    void borrowBookByAuthor(const vector<Book>& books, const string& author) {
        for (const auto& book : books) {
            if (book.author == author) {
                if (stock[book.title] > 0) {
                    stock[book.title]--;
                    cout << "[" << book.title << "] 책을 대여했습니다. 남은 재고: " << stock[book.title] << endl;
                }
                else {
                    cout << "[" << book.title << "] 책은 현재 모두 대여 중입니다." << endl;
                }
                return;
            }
        }
        cout << author << " 작가의 책이 없습니다." << endl;
    }

    // 반납 처리
    void returnBook(const string& title) {
        if (stock.find(title) != stock.end()) {
            stock[title]++;
            cout << "[" << title << "] 책을 반납했습니다. 현재 재고: " << stock[title] << endl;
        }
        else {
            cout << "[" << title << "] 책은 존재하지 않아 반납할 수 없습니다." << endl;
        }
    }

    // 모든 책 재고 출력
    void dispalyStock() {
        if (stock.empty()) {
            cout << "등록된 책이 없습니다." << endl;
            return;
        }

        cout << "현재 도서 재고 목록:" << endl;
        for (const auto& entry : stock) {
            cout << "- " << entry.first << " : " << entry.second << "권 남음" << endl;
        }
    }
};

int main() {
    BookManager manager;

    BorrowManager borrowManager;


    // 도서관 관리 프로그램의 기본 메뉴를 반복적으로 출력하여 사용자 입력을 처리합니다.
    // 프로그램 종료를 선택하기 전까지 계속 동작합니다.
    while (true) {
        cout << "\n도서관 관리 프로그램" << endl;
        cout << "1. 책 추가" << endl; // 책 정보를 입력받아 책 목록에 추가
        cout << "2. 모든 책 출력" << endl; // 현재 책 목록에 있는 모든 책 출력
        cout << "3. 책 제목 검색" << endl; // 현재 책 목록에 있는 책 제목 검색
        cout << "4. 작가 검색" << endl; // 현재 책 목록에 있는 책 작가 검색
        cout << "5. 책 제목으로 대여" << endl;
        cout << "6. 작가로 대여" << endl;
        cout << "7. 책 반납" << endl;
        cout << "8. 전체 재고 확인" << endl;
        cout << "9. 종료" << endl; // 프로그램 종료
        cout << "선택: ";

        int choice; // 사용자의 메뉴 선택을 저장
        cin >> choice;

        cin.ignore(); // 이전 입력의 잔여 버퍼를 제거

        if (choice == 1) {
            // 1번 선택: 책 추가
            // 사용자로부터 책 제목과 저자명을 입력받아 BookManager에 추가합니다.
            string title, author;
            cout << "책 제목: ";
            getline(cin, title); // 제목 입력 (공백 포함)
            cout << "책 저자: ";
            getline(cin, author); // 저자명 입력 (공백 포함)
            manager.addBook(title, author); // 입력받은 책 정보를 추가
            borrowManager.initializeStock(manager.getLastBooks());
        }
        else if (choice == 2) {
            // 2번 선택: 모든 책 출력
            // 현재 BookManager에 저장된 책 목록을 출력합니다.
            manager.displayAllBooks();
        }
        else if (choice == 3) {
            // 3번 선택: 제목 검색
            // 현재 책 목록에 있는 책 제목을 검색합니다.
            cout << "검색 할 책 제목: ";
            string title;
            getline(cin, title);

            manager.searchByTitle(title);
        }
        else if (choice == 4) {
            // 3번 선택: 작가 검색
            // 현재 책 목록에 있는 책 작가를 검색합니다.
            cout << "검색 할 작가: ";
            string author;
            getline(cin, author);
            
            manager.searchByAuthor(author);
        }
        else if (choice == 5) {
            // 5 번 선택: 책의 이름으로 대여
            //책의 이름으로 대여 여부를 검색하고 대여가 아닌 경우 대여할 수 있어야 합니다.            
            string title;
            cin.ignore();
            cout << "대여할 책 제목: ";
            getline(cin, title);
            borrowManager.borrowBookByTitle(manager.getBooks(), title);
        }
        else if (choice == 6) {
            // 6 번 선택: 작가의 이름으로 대여
            //작가의 이름으로 대여 여부를 검색하고 대여가 아닌 경우 대여할 수 있어야 합니다.    
            string author;
            cin.ignore();
            cout << "대여할 작가 이름: ";
            getline(cin, author);
            borrowManager.borrowBookByAuthor(manager.getBooks(), author);
        }
        else if (choice == 7) {
            // 7 번 선택: 책 반납
            //책을 반납할 수 있어야 합니다. 
            string title;
            cin.ignore();
            cout << "반납할 책 제목: ";
            getline(cin, title);
            borrowManager.returnBook(title);
        }
        else if (choice == 8) {
            // 8 번 선택: 재고 확인
            // 현재 등록된 책의 재고를 확인 합니다.
            borrowManager.dispalyStock();
        }
        else if (choice == 9) {
            // 3번 선택: 종료
            // 프로그램을 종료하고 사용자에게 메시지를 출력합니다.
            cout << "프로그램을 종료합니다." << endl;
            break; // while 루프 종료
        }
        else {
            // 잘못된 입력 처리
            // 메뉴에 없는 번호를 입력했을 경우 경고 메시지를 출력합니다.
            cout << "잘못된 입력입니다. 다시 시도하세요." << endl;
        }
    }

    return 0; // 프로그램 정상 종료
}

튜터님 코드

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;

class Book
{
public:
    string title;
    string author;

    Book(const string& title, const string& author)
        : title(title), author(author)
    {
    }
};

class BookManager
{
private:
    vector<Book> books;

public:
    void addBook(const string& title, const string& author)
    {
        books.push_back(Book(title, author));
        cout << "책이 추가되었습니다: " << title << " by " << author << endl;
    }

    void displayAllBooks() const
    {
        if (books.empty())
        {
            cout << "현재 등록된 책이 없습니다." << endl;
            return;
        }

        cout << "현재 도서 목록:" << endl;
        for (size_t i = 0; i < books.size(); i++)
        {
            cout << "- " << books[i].title << " by " << books[i].author << endl;
        }
    }

    void searchByTitle(const string& title)
    {
        // 범위 기반 포문 C++ 11
        for (Book& book : books)
        {
            if (title == book.title)
            {
                cout << "책 제목: " << title << "을(를) 찾았습니다." << endl;
                return;
            }
        }

        cout << title << "라는 책을 찾지 못했습니다." << endl;
    }

    void searchByAuthor(const string& author)
    {
        for (Book& book : books)
        {
            if (author == book.author)
            {
                cout << "책 제목: " << book.title << "을(를) 찾았습니다." << endl;
                return;
            }
        }

        cout << "저자 " << author << "의 책을 찾지 못했습니다." << endl;
    }

    Book* findBookByTitle(const string& title)
    {
        for (Book& book : books)
        {
            if (title == book.title)
            {
                return &book;
            }
        }

        return nullptr;
    }

    Book* findBookByAuthor(const string& author)
    {
        for (Book& book : books)
        {
            if (author == book.author)
            {
                return &book;
            }
        }

        return nullptr;
    }
};

//- 특정 책의 대여 여부를 알 수 있어야 합니다.
//- 책의 이름으로 대여 여부를 검색하고 대여가 아닌 경우 대여할 수 있어야 합니다.
//- 책의 작가로 대여 여부를 검색하고 대여가 아닌 경우 대여할 수 있어야 합니다.
//- 책을 반납할 수 있어야 합니다.
//- 모든 책의 재고는 난이도를 낮추기 위해 3권으로 통일 합니다.

class BorrowManager
{
private:
    unordered_map<string, int> stock;

public:
    void initializeStock(const Book* book, int quantity = 3)
    {
        if (nullptr == book)
        {
            return;
        }

        stock[book->title] = quantity;
        cout << "책이 추가되었습니다: " << book->title << " by " << book->author << endl;
    }

    void borrowBook(const string& title)
    {
        if (stock.end() != stock.find(title))
        {
            if (0 < stock[title])
            {
                --stock[title];
                cout << title << "을(를) 대여했습니다." << endl;
            }

            else
            {
                cout << "재고가 부족하여 " << title << "을(를) 대여하지 못했습니다." << endl;
            }
        }

        else
        {
            cout << title << "이라는 책을 찾지 못했습니다." << endl;
        }
    }

    void returnBook(const string& title)
    {
        if (stock.end() != stock.find(title))
        {
            if (3 > stock[title])
            {
                ++stock[title];
                cout << title << "을(를) 반납했습니다." << endl;
            }

            else
            {
                cout << title << "을(를) 반납하지 못했습니다." << endl;
            }
        }

        else
        {
            cout << title << "이라는 책을 찾지 못했습니다." << endl;
        }
    }

    void displayStock()
    {
        for (pair<const string, int> e : stock)
        {
            cout << "책 제목: " << e.first << "책 재고: " << e.second << endl;
        }
    }
};

int main()
{
    BookManager bookManager;
    BorrowManager borrowManager;

    bookManager.addBook("홍길동전", "허균");
    bookManager.addBook("반지의 제왕", "J.R.P 톨킨");

    borrowManager.initializeStock(bookManager.findBookByTitle("홍길동전"));
    borrowManager.initializeStock(bookManager.findBookByTitle("반지의 제왕"));

    while (true)
    {
        system("cls");

        cout << "\n도서관 관리 프로그램" << endl;
        cout << "1. 책 목록 출력" << endl;
        cout << "2. 책 대여" << endl;
        cout << "3. 책 반납" << endl;
        cout << "4. 책 재고 출력" << endl;
        cout << "5. 종료" << endl;
        cout << "선택: ";

        int choice;
        cin >> choice;
        cin.ignore();

        if (1 == choice)
        {
            bookManager.displayAllBooks();
        }
        else if (2 == choice)
        {
            cout << "대여할 책 제목 또는 작가 이름: ";
            string query;
            getline(cin, query);

            Book* book = bookManager.findBookByTitle(query);

            if (book)
            {
                borrowManager.borrowBook(book->title);
            }

            else
            {
                book = bookManager.findBookByAuthor(query);

                if (book)
                {
                    borrowManager.borrowBook(book->title);
                }
                else
                {
                    cout << "관련된 책 정보가 존재하지 않습니다." << endl;
                }
            }
        }
        else if (3 == choice)
        {
            cout << "반납할 책 제목 또는 작가 이름: ";
            string query;
            getline(cin, query);

            Book* book = bookManager.findBookByTitle(query);

            if (book)
            {
                borrowManager.returnBook(book->title);
            }

            else
            {
                book = bookManager.findBookByAuthor(query);

                if (book)
                {
                    borrowManager.returnBook(book->title);
                }
                else
                {
                    cout << "관련된 책 정보가 존재하지 않습니다." << endl;
                }
            }
        }
        else if (4 == choice)
        {
            borrowManager.displayStock();
        }
        else if (5 == choice)
        {
            cout << "프로그램을 종료합니다." << endl;
            break;
        }
        else
        {
            cout << "잘못된 입력입니다. 다시 시도하세요." << endl;
        }

        system("pause");
    }

    return 0;
}

💡알게 된 것

   Book* findBookByTitle(const string& title)
    {
        for (Book& book : books)
        {
            if (title == book.title)
            {
                return &book;
            }
        }

        return nullptr;
    }

타이틀을 검색해서 빌리는 부분을 어렵게 했었는데 저런 경우엔 레퍼런스보단 포인터를 사용하는 게 좋을 거 같다.

profile
누군가에게 추억을 만들어주는 그날까지

0개의 댓글