Book ID

I am not sure how to deal with one issue with my project.
I have library with books (created using vector and smart pointers) [this is an exercise to learn how to deal with vector and unique_ptr] user can borrow book from library and return it back to library. at the moment I am using vector index as a way of selecting correct book, however, there are few issues with that method.
1st
If I have:

book index 0
title aaaaaaa
author aaaa
publication year 1111

book index 1
title bbbbbbb
author bbbb
publication year 2222

if I borrow book index 1 (bbbbb book) in user vector it will have ID 0 as this is going to be 1st book in vector.

2nd
if I want to return this book now back to Libray I have following situation

book index 0
title aaaaaaa
author aaaa
publication year 1111

book index 1
Book Borrowed

book index 2
title bbbbbbb
author bbbb
publication year 2222

------
what I would like to get is more control what book ID is going to be?
Can I have situation where book that I return will be returned to index 1 (as in the example above) rather then creating new index?
How should this be created? as static number?
should that be part of book (i think it should be part of book) or should that be part of library?

for reference I am providing my code :)

thank you for your time and help :)

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
  #include <iostream>
#include <string>
#include <vector>
#include <memory>
//#include <experimental/string_view>

class Book
{
private:
    std::string title;
    std::string author;
    int publication_year;
public:
    //Book(std::experimental::string_view title, std::experimental::string_view author, int publication_year) : title(title), author(author), publication_year(publication_year)
    //{}
    Book(std::string title, std::string author, int publication_year) : title(title), author(author), publication_year(publication_year)
    {}

    void const printB() {
        std::cout << "Title: " << title << '\n';
        std::cout << "Author: " << author << '\n';
        std::cout << "Publication Year: " << publication_year << '\n';
    }
};
class Library
{
private:
    std::vector<std::unique_ptr<Book>> shelf_with_books;
public:
    void Reserve(unsigned int size) // done
    {
        shelf_with_books.reserve(size);
    }
    void Add(std::unique_ptr<Book> bk) // done
    {
        shelf_with_books.push_back(std::move(bk));
    }
   std::unique_ptr<Book> Borrow(unsigned int book_selection)
    {
        return std::move(shelf_with_books.at(book_selection));
    }
    void Return(std::unique_ptr<Book> book)
    {
        shelf_with_books.push_back(std::move(book));
    }
    void const Print() // done
    {
        std::cout << "Capacity: " << shelf_with_books.capacity() << " size: " << shelf_with_books.size() << '\n';
        unsigned int i = 0;
        for (auto &shelf_with_book : shelf_with_books) {
            std::cout << '\n';
            if (shelf_with_book != nullptr)
            {
                std::cout << "Book ID: " << i << '\n';
                shelf_with_book->printB();
                i++;
            } else {
                std::cout << "Book ID: " << i << '\n';
                std::cout << "Book is borrowed \n";
                i++;
            }
            std::cout << "-----------------" << '\n';
        }
    }
};
class Person
{
private:
    std::vector<std::unique_ptr<Book>> user_books;
public:
   /* void Reserve(unsigned int size, std::unique_ptr<Book> bk) // not sure if I will need this at all
    {
        user_books.reserve(size);
        user_books.push_back(std::move(bk));
    }*/
    void Borrow(std::unique_ptr<Book> book)
    {
        user_books.push_back(std::move(book));
    }
    std::unique_ptr<Book> Return(unsigned int book_selection)
    {
        return std::move(user_books.at(book_selection));
    }
    void const Print() // done
    {
        std::cout << "Capacity: " << user_books.capacity() << " size: " << user_books.size() << '\n';
        unsigned int i = 0;
        for (auto &user_book : user_books) {
            if (user_book != nullptr)
            {
                std::cout << '\n';
                std::cout << "Book ID: " << i << '\n';
                user_book->printB();
                i++;
                std::cout << "-----------------" << '\n';
            } else{
                std::cout << "User don't have any books! \n";
                std::cout << "Go get some :) \n";
            }
        }
    }
};

char menu();

int main() {
    Library lib;
    Person person;
    bool shouldExit = true;
    do {
        switch (menu()) {
            case '1': {
                std::system("clear");
                std::cout << "Max amount books in Library: ";
                unsigned int librarySize = 0;
                std::cin >> librarySize;
                lib.Reserve(librarySize);
                std::cout << '\n';
                std::cout << "library can store " << librarySize << " books\n";
                std::cout << '\n';
                break;
            }
            case '2': {
                std::cout << "How many books do you want to add? ";
                unsigned int number_of_books = 0;
                std::cin >> number_of_books;
                for (size_t i = 0; i != number_of_books; i++) {
                    std::string author, title;
                    int publication_year = 0;
                    std::cout << "ID " << i << '\n';
                    std::cout << "Title: ";
                    std::cin >> title;
                    std::cout << "Author: ";
                    std::cin >> author;
                    std::cout << "Publication year: ";
                    std::cin >> publication_year;
                    std::unique_ptr<Book> book_ptr = std::make_unique<Book>(title, author, publication_year);
                    lib.Add(std::move(book_ptr));
                    std::cout << '\n';
                }
                std::system("clear");
                break;
            }
            case '3': {
                std::cout << "Please select book to borrow: ";
                lib.Print();
                unsigned int book_selection = 0;
                std::cin >> book_selection;
                std::system("clear");
                if (lib.Borrow(book_selection) != nullptr)
                {
                    std::unique_ptr<Book> borrow_book_ptr = lib.Borrow(book_selection);
                    person.Borrow(std::move(borrow_book_ptr));
                } else{
                    std::cout << "This book is already borrowed!\n";
                }
                break;
            }
            case '4': {
                std::cout << "Please select book to return: ";
                person.Print();
                unsigned int book_selection = 0;
                std::cin >> book_selection;
                std::unique_ptr<Book>return_book_ptr = person.Return(book_selection);
                lib.Return(std::move(return_book_ptr));
                std::system("clear");
                break;
            }
            case '5': {
                std::system("clear");
                std::cout << "Printing books in Library\n";
                lib.Print();
                break;
            }
            case '6': {
                std::system("clear");
                person.Print();
                break;
            }
            case '9': {
                shouldExit = false;
                break;
            }
            default:
            {
                std::system("clear");
                std::cout << "so good its Friday :)  \n";
            }
        }
    } while (shouldExit);
    return 0;
}

char menu() {
    char choice {' '};
    std::cout << "Please make your selection\n";
    std::cout << "Press number: \n";
    std::cout << "1 - Set size of the Library\n";
    std::cout << "2 - Create book\n";
    std::cout << "3 - Borrow book\n";
    std::cout << "4 - Return book\n";
    std::cout << "5 - Print out all books\n";
    std::cout << "6 - Print books borrowed by user\n";
   // std::cout << "7 - Print books borrowed by Librarian\n";
    std::cout << "9 - to Quit\n";
    std::cin >> choice;

    return choice;
}
An idea - I don't know whether it is a good one - add an extra member variable to Book, which will be the library location from where it was borrowed. Most of the time this variable will be unused, but it could be assigned a value at the time of borrowing, so that the book can later be returned to the same position (with appropriate checking that the location is indeed empty).
hmmm interesting,
I had in earlier version of this project that used unique number for each created book. I used dynamic version of ID, however that would probably required some changes to current design as I am using index as reference point with push_back.

Thinking aloud:
so your idea would be to add another variable (unsigend int ID;)
then when book is inside Libray I would read index number, update book with this.

so book is created
Title: aaaaaaaaaaa
author: aaaa
Publication year: 11111
ID:; // somehow I would have to make it empty to prevent false positive if i use starting number such as 0 or 9999 (there could be book with such number)

then book is inside library, somehow I would have to read index number and set it. Lets see index is 0.
Title: aaaaaaaaaaa
author: aaaa
Publication year: 11111
Book ID:0
ID: 0


then I move book to user, and book is moved to for example index 1 (as there is already something in index 0)
Title: aaaaaaaaaaa
author: aaaa
Publication year: 11111
Book ID:1
ID: 0 // library ID is 0 so it must be back at ID 0 ???

then modify return function and restore back to ID position.

however that sounds a bit messy with different book id.

alternative would when moved to user vector insert to same ID as it was in library
so if in Library book was at index 0 I would insert it at ID 0, if book had index 5 I would insert it at user index 5.
on other hand that is messy as well.

any other ways of dealing with such situation?
The idea of storing the book at the same index in the User as in the Library. If the users books are stored in a vector, and the library has 100000 books, it would mean the user must also have 100000 books (most of them empty).

Instead, maybe use a std::map to hold the users books. This way, there is no need for any extra variable inside the Book. Instead, the map will associate the book with the index number.
i never used map so lets me read about this :)

thank you!
Topic archived. No new replies allowed.