Skip to content

Commit 2158871

Browse files
authored
Merge pull request #29 from Satvik-Singh192/feature/library-management-system
feat: implement Library Management System in C++ using OOP principles
2 parents ff1357a + 1cde7a4 commit 2158871

File tree

3 files changed

+403
-0
lines changed

3 files changed

+403
-0
lines changed
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
#include "LibraryManagement.h"
2+
3+
// ------------ helpers ------------
4+
static inline string trim(const string &s) {
5+
size_t a = s.find_first_not_of(" \t\r\n");
6+
if (a == string::npos) return "";
7+
size_t b = s.find_last_not_of(" \t\r\n");
8+
return s.substr(a, b - a + 1);
9+
}
10+
11+
static inline string lower(const string &s) {
12+
string t = s;
13+
transform(t.begin(), t.end(), t.begin(), ::tolower);
14+
return t;
15+
}
16+
17+
// ------------ Book ------------
18+
Book::Book() : id(-1), totalCopies(0), availableCopies(0) {}
19+
Book::Book(int i, string t, string a, string c, int copies)
20+
: id(i), title(move(t)), author(move(a)), category(move(c)),
21+
totalCopies(copies), availableCopies(copies) {}
22+
23+
int Book::getId() const { return id; }
24+
string Book::getTitle() const { return title; }
25+
string Book::getAuthor() const { return author; }
26+
string Book::getCategory() const { return category; }
27+
int Book::getTotalCopies() const { return totalCopies; }
28+
int Book::getAvailableCopies() const { return availableCopies; }
29+
30+
void Book::setTitle(const string &t) { title = t; }
31+
void Book::setAuthor(const string &a) { author = a; }
32+
void Book::setCategory(const string &c) { category = c; }
33+
void Book::setTotalCopies(int c) {
34+
if (c < 0) throw runtime_error("Total copies cannot be negative");
35+
int issued = totalCopies - availableCopies;
36+
if (c < issued) throw runtime_error("Cannot set total copies less than already issued copies");
37+
totalCopies = c;
38+
availableCopies = c - issued;
39+
}
40+
41+
bool Book::issueOne() {
42+
if (availableCopies <= 0) return false;
43+
--availableCopies;
44+
return true;
45+
}
46+
47+
bool Book::returnOne() {
48+
if (availableCopies >= totalCopies) return false;
49+
++availableCopies;
50+
return true;
51+
}
52+
53+
string Book::toCSV() const {
54+
return to_string(id) + "," + title + "," + author + "," + category + "," +
55+
to_string(totalCopies) + "," + to_string(availableCopies);
56+
}
57+
58+
Book Book::fromCSV(const string &line) {
59+
stringstream ss(line);
60+
string id, t, a, c, total, avail;
61+
getline(ss, id, ',');
62+
getline(ss, t, ',');
63+
getline(ss, a, ',');
64+
getline(ss, c, ',');
65+
getline(ss, total, ',');
66+
getline(ss, avail, ',');
67+
Book b;
68+
b = Book(stoi(id), trim(t), trim(a), trim(c), stoi(total));
69+
b.setTotalCopies(stoi(total));
70+
while (b.getAvailableCopies() > stoi(avail)) b.issueOne();
71+
return b;
72+
}
73+
74+
// ------------ Member ------------
75+
Member::Member() : id(-1) {}
76+
Member::Member(int i, string n, string e) : id(i), name(move(n)), email(move(e)) {}
77+
78+
int Member::getId() const { return id; }
79+
string Member::getName() const { return name; }
80+
string Member::getEmail() const { return email; }
81+
82+
void Member::setName(const string &n) { name = n; }
83+
void Member::setEmail(const string &e) { email = e; }
84+
85+
string Member::toCSV() const { return to_string(id) + "," + name + "," + email; }
86+
87+
Member Member::fromCSV(const string &line) {
88+
stringstream ss(line);
89+
string id, n, e;
90+
getline(ss, id, ',');
91+
getline(ss, n, ',');
92+
getline(ss, e, ',');
93+
return Member(stoi(id), trim(n), trim(e));
94+
}
95+
96+
// ------------ Library ------------
97+
Library::Library() { loadAll(); }
98+
Library::~Library() { saveAll(); }
99+
100+
void Library::loadAll() {
101+
ifstream fb(booksFile);
102+
if (fb) {
103+
string line;
104+
while (getline(fb, line))
105+
if (!trim(line).empty()) {
106+
Book b = Book::fromCSV(line);
107+
books[b.getId()] = b;
108+
nextBookId = max(nextBookId, b.getId() + 1);
109+
}
110+
}
111+
112+
ifstream fm(membersFile);
113+
if (fm) {
114+
string line;
115+
while (getline(fm, line))
116+
if (!trim(line).empty()) {
117+
Member m = Member::fromCSV(line);
118+
members[m.getId()] = m;
119+
nextMemberId = max(nextMemberId, m.getId() + 1);
120+
}
121+
}
122+
}
123+
124+
void Library::saveAll() {
125+
ofstream fb(booksFile);
126+
for (auto &[_, b] : books)
127+
fb << b.toCSV() << "\n";
128+
129+
ofstream fm(membersFile);
130+
for (auto &[_, m] : members)
131+
fm << m.toCSV() << "\n";
132+
}
133+
134+
// Books
135+
int Library::addBook(const string &t, const string &a, const string &c, int copies) {
136+
int id = nextBookId++;
137+
books[id] = Book(id, t, a, c, copies);
138+
return id;
139+
}
140+
141+
void Library::updateBook(int id, const optional<string> &t, const optional<string> &a,
142+
const optional<string> &c, const optional<int> &copies) {
143+
auto it = books.find(id);
144+
if (it == books.end()) throw runtime_error("Book not found");
145+
if (t) it->second.setTitle(*t);
146+
if (a) it->second.setAuthor(*a);
147+
if (c) it->second.setCategory(*c);
148+
if (copies) it->second.setTotalCopies(*copies);
149+
}
150+
151+
void Library::deleteBook(int id) {
152+
if (!books.count(id)) throw runtime_error("Book not found");
153+
books.erase(id);
154+
}
155+
156+
vector<Book> Library::listBooks() const {
157+
vector<Book> v;
158+
for (auto &[_, b] : books) v.push_back(b);
159+
sort(v.begin(), v.end(), [](auto &x, auto &y){return x.getId()<y.getId();});
160+
return v;
161+
}
162+
163+
vector<Book> Library::searchByTitle(const string &q) const {
164+
vector<Book> r;
165+
for (auto &[_, b] : books)
166+
if (lower(b.getTitle()).find(lower(q)) != string::npos)
167+
r.push_back(b);
168+
return r;
169+
}
170+
171+
vector<Book> Library::searchByAuthor(const string &q) const {
172+
vector<Book> r;
173+
for (auto &[_, b] : books)
174+
if (lower(b.getAuthor()).find(lower(q)) != string::npos)
175+
r.push_back(b);
176+
return r;
177+
}
178+
179+
vector<Book> Library::searchByCategory(const string &q) const {
180+
vector<Book> r;
181+
for (auto &[_, b] : books)
182+
if (lower(b.getCategory()).find(lower(q)) != string::npos)
183+
r.push_back(b);
184+
return r;
185+
}
186+
187+
// Members
188+
int Library::addMember(const string &n, const string &e) {
189+
int id = nextMemberId++;
190+
members[id] = Member(id, n, e);
191+
return id;
192+
}
193+
194+
void Library::updateMember(int id, const optional<string>& n, const optional<string>& e) {
195+
auto it = members.find(id);
196+
if (it == members.end()) throw runtime_error("Member not found");
197+
if (n) it->second.setName(*n);
198+
if (e) it->second.setEmail(*e);
199+
}
200+
201+
void Library::deleteMember(int id) {
202+
if (!members.count(id)) throw runtime_error("Member not found");
203+
members.erase(id);
204+
}
205+
206+
vector<Member> Library::listMembers() const {
207+
vector<Member> v;
208+
for (auto &[_, m] : members) v.push_back(m);
209+
sort(v.begin(), v.end(), [](auto &x, auto &y){return x.getId()<y.getId();});
210+
return v;
211+
}
212+
213+
// Transactions
214+
void Library::issueBook(int memberId, int bookId) {
215+
if (!members.count(memberId)) throw runtime_error("Invalid member");
216+
if (!books.count(bookId)) throw runtime_error("Invalid book");
217+
if (!books[bookId].issueOne()) throw runtime_error("No available copies");
218+
transactions.push_back({memberId, bookId, "2025-10-23", false});
219+
}
220+
221+
void Library::returnBook(int memberId, int bookId) {
222+
if (!members.count(memberId)) throw runtime_error("Invalid member");
223+
if (!books.count(bookId)) throw runtime_error("Invalid book");
224+
books[bookId].returnOne();
225+
for (auto &tx : transactions)
226+
if (tx.memberId == memberId && tx.bookId == bookId && !tx.returned) {
227+
tx.returned = true;
228+
return;
229+
}
230+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#ifndef LIBRARYMANAGEMENT_H
2+
#define LIBRARYMANAGEMENT_H
3+
4+
#include <bits/stdc++.h>
5+
using namespace std;
6+
7+
// ---------------- Book ----------------
8+
class Book {
9+
int id;
10+
string title, author, category;
11+
int totalCopies, availableCopies;
12+
13+
public:
14+
Book();
15+
Book(int id, string title, string author, string category, int copies);
16+
17+
int getId() const;
18+
string getTitle() const;
19+
string getAuthor() const;
20+
string getCategory() const;
21+
int getTotalCopies() const;
22+
int getAvailableCopies() const;
23+
24+
void setTitle(const string&);
25+
void setAuthor(const string&);
26+
void setCategory(const string&);
27+
void setTotalCopies(int);
28+
29+
bool issueOne();
30+
bool returnOne();
31+
32+
string toCSV() const;
33+
static Book fromCSV(const string&);
34+
};
35+
36+
// ---------------- Member ----------------
37+
class Member {
38+
int id;
39+
string name, email;
40+
41+
public:
42+
Member();
43+
Member(int id, string name, string email);
44+
45+
int getId() const;
46+
string getName() const;
47+
string getEmail() const;
48+
49+
void setName(const string&);
50+
void setEmail(const string&);
51+
52+
string toCSV() const;
53+
static Member fromCSV(const string&);
54+
};
55+
56+
// ---------------- Transaction ----------------
57+
struct Transaction {
58+
int memberId;
59+
int bookId;
60+
string date;
61+
bool returned;
62+
};
63+
64+
// ---------------- Library ----------------
65+
class Library {
66+
unordered_map<int, Book> books;
67+
unordered_map<int, Member> members;
68+
vector<Transaction> transactions;
69+
70+
int nextBookId = 1;
71+
int nextMemberId = 1;
72+
73+
const string booksFile = "books.csv";
74+
const string membersFile = "members.csv";
75+
const string txFile = "transactions.csv";
76+
77+
void loadAll();
78+
void saveAll();
79+
80+
public:
81+
Library();
82+
~Library();
83+
84+
// Books
85+
int addBook(const string&, const string&, const string&, int);
86+
void updateBook(int, const optional<string>&, const optional<string>&, const optional<string>&, const optional<int>&);
87+
void deleteBook(int);
88+
vector<Book> listBooks() const;
89+
vector<Book> searchByTitle(const string&) const;
90+
vector<Book> searchByAuthor(const string&) const;
91+
vector<Book> searchByCategory(const string&) const;
92+
93+
// Members
94+
int addMember(const string&, const string&);
95+
void updateMember(int, const optional<string>&, const optional<string>&);
96+
void deleteMember(int);
97+
vector<Member> listMembers() const;
98+
99+
// Transactions
100+
void issueBook(int memberId, int bookId);
101+
void returnBook(int memberId, int bookId);
102+
};
103+
104+
#endif

0 commit comments

Comments
 (0)