기존 도서관 관리 프로그램에 검색 기능을 추가해주세요
필수 기능 구현 완료 후 전체적인 구조를 그리면 아래와 같습니다.
어디까지나 참조일 뿐 꼭 이대로 구현할 필요는 없습니다.

기존 도서관 관리 프로그램에 필수 기능을 추가한 상태에서 아래 대여 기능을 추가해주세요
도전 기능 구현까지 완료한 후 전체적인 구조를 그리면 아래와 같습니다.
어디까지나 참조일 뿐 꼭 이대로 구현할 필요는 없습니다.

#include <iostream>
#include <vector>
#include <string>
using namespace std; // namespace std 사용
class Book {
public:
string title;
string author;
int stock; // 책 재고
Book(const string& title, const string& author)
: title(title), author(author), stock(3) {
}
// 대여 기능
bool rentBook()
{
if (stock > 0) // 재고 있으면 대여 가능
{
stock--; // 대여 시 재고 1권 감소
return true;
}
return false; // 재고 없으면 대여 불가
}
// 반납 기능
void returnBook()
{
stock++; // 반납 시 재고 1권 증가
}
};
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 searchBookByTitle(const string& title)
{
bool found = false; // 아직 책을 못 찾은 상태
// books.size()는 books에 들어있는 원소(책)의 개수를 반환하는 함수
for (size_t i = 0; i < books.size(); i++)
{
if (books[i].title == title) // i번째 책 제목이 내가 찾는 제목과 일치
{
cout << "책 제목: " << books[i].title << " 작가: " << books[i].author;
cout << " 재고: " << books[i].stock << "권" << endl;
found = true; // for문 돌면서 책 찾으면 true
break;
}
}
if (!found)
{
cout << "해당 제목의 책을 찾을 수 없습니다." << endl;
}
}
// 책 대여
void rentBookByTitle(const string& title)
{
for (size_t i = 0; i < books.size(); i++)
{
if (books[i].title == title) // i번째 책 제목이 내가 찾는 제목과 일치
{
if (books[i].rentBook())
{
cout << "책 '" << title << "' 대여가 완료되었습니다." << endl;
}
else
{
cout << "책 '" << title << "'은 대여할 수 없습니다." << endl; // 재고부족
}
return; // 함수 종료, 반환값 없음
}
}
// for문을 다 돌았는데 return이 안 됐으면 책이 없는 것
cout << "해당 제목의 책을 찾을 수 없습니다." << endl;
}
// 책 반납
void returnBookByTitle(const string& title)
{
for (size_t i = 0; i < books.size(); i++)
{
if (books[i].title == title)
{
books[i].returnBook();
cout << "책 '" << title << "'이 반납되었습니다." << endl;
return;
}
}
cout << "해당 제목의 책을 찾을 수 없습니다." << endl;
}
};
int main()
{
BookManager manager;
// 도서관 관리 프로그램의 기본 메뉴를 반복적으로 출력하여 사용자 입력을 처리합니다.
// 프로그램 종료를 선택하기 전까지 계속 동작합니다.
while (true)
{
cout << "\n도서관 관리 프로그램" << endl;
cout << "1. 책 추가" << endl; // 책 정보를 입력받아 책 목록에 추가
cout << "2. 모든 책 출력" << endl; // 현재 책 목록에 있는 모든 책 출력
cout << "3. 제목으로 책 검색" << endl;
cout << "4. 책 대여" << endl;
cout << "5. 책 반납" << endl;
cout << "6. 종료" << endl; // 프로그램 종료
cout << "선택: ";
int choice; // 사용자의 메뉴 선택을 저장
cin >> choice;
if (choice == 1)
{
// 1번 선택: 책 추가
// 사용자로부터 책 제목과 저자명을 입력받아 BookManager에 추가합니다.
string title, author; // 책 제목, 저장명 저장할 변수 선언
cout << "책 제목: ";
cin.ignore(); // 이전 입력의 잔여 버퍼를 제거 -> 새로운 입력 받을 준비
getline(cin, title); // 제목 입력 (공백 포함) 받아 title에 저장
cout << "책 저자: ";
getline(cin, author); // 저자명 입력 (공백 포함) 받아 author에 저장
manager.addBook(title, author); // 입력받은 책 정보를 추가
}
else if (choice == 2)
{
// 2번 선택: 모든 책 출력
// 현재 BookManager에 저장된 책 목록을 출력합니다.
manager.displayAllBooks();
}
else if (choice == 3)
{
// 3번 선택: 제목으로 책 검색
string title;
cout << "책 제목: ";
cin.ignore();
getline(cin, title);
manager.searchBookByTitle(title);
}
else if (choice == 4)
{
// 4번 선택: 책 대여
string title;
cout << "책 제목: ";
cin.ignore();
getline(cin, title);
manager.rentBookByTitle(title);
}
else if (choice == 5)
{
// 5번 선택: 책 반납
string title;
cout << "책 제목: ";
cin.ignore();
getline(cin, title);
manager.returnBookByTitle(title);
}
else if (choice == 6)
{
// 3번 선택: 종료
// 프로그램을 종료하고 사용자에게 메시지를 출력합니다.
cout << "프로그램을 종료합니다." << endl;
break; // while 루프 종료
}
else
{
// 잘못된 입력 처리
// 메뉴에 없는 번호를 입력했을 경우 경고 메시지를 출력합니다.
cout << "잘못된 입력입니다. 다시 시도하세요." << endl;
}
}
return 0; // 프로그램 정상 종료
}
searchBookByTitle() 와 searchBookByAuthor() 함수 추가Book(const string& title, const string& author)
: title(title), author(author), stock(3) {
}
Book(const string& title, const string& author) : 생성자 선언 title 과 author 라는 매개변수를 받아서 객체의 멤버 변수들을 초기화함title(title), author(author), stock(3), isRented(false) : 생성자 초기화 리스트title(title) - 객체의 title 멤버 변수를 생성자의 매개변수 title로 초기화author(author) - author 멤버 변수를 생성자의 매개변수 author로 초기화stock(3) - stock 멤버 변수를 3으로 초기화생성자 초기화 리스트
title, author, stock 가 생성자 초기화 리스트로 초기화 된 것// 생성자 초기화 리스트 X
class Book {
private:
int stock;
public:
Book(int s) { // 생성자
stock = s; // 멤버 변수에 대입
}
};
// 생성자 초기화 리스트 O
class Book {
private:
int stock;
public:
Book(int s) : stock(s) { // 초기화 리스트
// 생성자 본문은 비워두거나 추가 로직을 넣을 수 있음
}
};
멤버 초기화 리스트
// 멤버 초기화 리스트 X
// 생성 → 기본값 → 대입
MyClass() {
member = 10; // 생성자 호출 후 기본값이 먼저 설정된 뒤, 대입됨
}
// 멤버 초기화 리스트 O
MyClass() : member(10) {
// 여기 오기 전에 이미 member가 10으로 초기화됨, 생성 → 초기화
}
};
| 구분 | 생성자 본문에서 대입 | 생성자 초기화 리스트 |
|---|---|---|
| 초기화 시점 | 객체가 생성된 후에 값 할당 (기본값이 먼저 설정된 후) | 생성자 호출 시 바로 멤버 변수 초기화 |
| 초기화 방식 | 생성자 내부에서 멤버 변수에 값을 대입 | 생성자 호출 시 초기화 리스트에서 바로 값 대입 |
| 기본값 설정 | 생성자 호출 후, 멤버 변수를 설정 가능 | 클래스 내에서 멤버 변수를 선언할 때 기본값을 설정 |
| 초기화 시점의 차이점 | 객체가 생성된 후, 기본값을 설정한 뒤 대입 | 생성자 호출 시, 바로 멤버 변수 초기화 |
| 장점 | 생성자 본문에서 로직을 작성하면서 초기화할 수 있음 | 객체 생성 시 바로 초기화되므로 더 효율적이고 직관적임 |
| 사용 예시 | stock = 10; | : stock(10) |
const string& title, const string& author:const string& title : title은 책 제목을 저장하는 매개변수const : 이 매개변수가 함수 내부에서 변경되지 않게 함string : 문자열 타입& : 참조(reference) - 메모리의 주소를 직접 전달해 복사 없이 원본 값을 변경할 수 있게 해줌books.size()는 books에 들어있는 원소(책)의 개수를 반환하는 함수
size_t books : 여러 책(Book)이 들어있는 vectori : for문에서 사용하는 인덱스 (0, 1, 2, ...)books[i] : i번째 책을 의미함books[i].title : i번째 책의 제목을 의미books[i].title == title.(dot) 연산자if (books[i].title == title)
책 제목이 일치할 때
bool rentBook()
{
if (stock > 0) // 재고 있으면 대여 가능
{
stock--; // 대여 시 재고 1권 감소
return true;
}
return false; // 재고 없으면 대여 불가
}
만약 rentBook() 이 false를 반환
→ 책 제목은 일치하지만 재고가 0이라서 더 이상 대여할 수 없다는 뜻입니다.
만약 for문을 끝까지 돌았는데 books[i].title == title 이 한 번도 참이 아님
→ 아예 그런 제목의 책 자체가 없는 것
| 인덱스(i) | books[i].title | books[i].stock |
|---|---|---|
| 0 | C++ 기초 | 2 |
| 1 | 파이썬 입문 | 0 |
| 2 | 블루프린트 마스터 | 3 |
1️⃣ 사용자가 "파이썬 입문"을 찾는다
2️⃣ i=1 에서 books.title == "파이썬 입문" → 참!
3️⃣ 그런데 books.stock == 0 이므로 rentBook() 은 false를 반환 → 재고 부족
1️⃣ 사용자가 "블루프린트 기초"를 찾는다
2️⃣ 인덱스 0, 1, 2 모두 title이 "블루프린트 기초"가 아님 → 책 자체가 없음
정리
if (books[i].title == title) 가 참일 때rentBook() 가 false)cin 을 사용할 때 이전에 입력한 값이 입력 버퍼에 남아있는 경우가 있음 cin 으로 숫자나 다른 문자열을 입력받은 후 getline 을 사용하려면 입력 버퍼를 비워줘야 한다cin.ignore(); 를 사용// getline 함수 정의
getline(입력스트림, 저장변수);
cin
getline
클래스 (Class) = 설계도객체 (Object)클래스 자체는 설계도로 사용되며, 실제 프로그램에서 함수나 변수를 호출하는 데 객체를 사용함
객체를 통해 클래스 내에서 정의된 함수(메서드)에 접근할 수 있음
BookManager manager; // 객체 생성
manager.addBook("C++", "홍길동"); // 객체를 통해 메서드 호출
manager.addBook() 은 manager 라는 객체를 통해 BookManager 클래스의 addBook 메서드에 접근함
➡ 메서드는 객체를 통해 호출하고 클래스 자체는 함수 호출에 직접 사용되지 않는다