From 1cde7a44b4a090427b0b9c54947cca8d7ef336e2 Mon Sep 17 00:00:00 2001 From: Satvik-Singh192 Date: Thu, 23 Oct 2025 16:14:29 +0530 Subject: [PATCH] feat: implement Library Management System in C++ using OOP principles --- Src/Library_Managment/LibraryManagement.cpp | 230 ++++++++++++++++++++ Src/Library_Managment/LibraryManagement.h | 104 +++++++++ Src/Library_Managment/main.cpp | 69 ++++++ 3 files changed, 403 insertions(+) create mode 100644 Src/Library_Managment/LibraryManagement.cpp create mode 100644 Src/Library_Managment/LibraryManagement.h create mode 100644 Src/Library_Managment/main.cpp diff --git a/Src/Library_Managment/LibraryManagement.cpp b/Src/Library_Managment/LibraryManagement.cpp new file mode 100644 index 0000000..9227da8 --- /dev/null +++ b/Src/Library_Managment/LibraryManagement.cpp @@ -0,0 +1,230 @@ +#include "LibraryManagement.h" + +// ------------ helpers ------------ +static inline string trim(const string &s) { + size_t a = s.find_first_not_of(" \t\r\n"); + if (a == string::npos) return ""; + size_t b = s.find_last_not_of(" \t\r\n"); + return s.substr(a, b - a + 1); +} + +static inline string lower(const string &s) { + string t = s; + transform(t.begin(), t.end(), t.begin(), ::tolower); + return t; +} + +// ------------ Book ------------ +Book::Book() : id(-1), totalCopies(0), availableCopies(0) {} +Book::Book(int i, string t, string a, string c, int copies) + : id(i), title(move(t)), author(move(a)), category(move(c)), + totalCopies(copies), availableCopies(copies) {} + +int Book::getId() const { return id; } +string Book::getTitle() const { return title; } +string Book::getAuthor() const { return author; } +string Book::getCategory() const { return category; } +int Book::getTotalCopies() const { return totalCopies; } +int Book::getAvailableCopies() const { return availableCopies; } + +void Book::setTitle(const string &t) { title = t; } +void Book::setAuthor(const string &a) { author = a; } +void Book::setCategory(const string &c) { category = c; } +void Book::setTotalCopies(int c) { + if (c < 0) throw runtime_error("Total copies cannot be negative"); + int issued = totalCopies - availableCopies; + if (c < issued) throw runtime_error("Cannot set total copies less than already issued copies"); + totalCopies = c; + availableCopies = c - issued; +} + +bool Book::issueOne() { + if (availableCopies <= 0) return false; + --availableCopies; + return true; +} + +bool Book::returnOne() { + if (availableCopies >= totalCopies) return false; + ++availableCopies; + return true; +} + +string Book::toCSV() const { + return to_string(id) + "," + title + "," + author + "," + category + "," + + to_string(totalCopies) + "," + to_string(availableCopies); +} + +Book Book::fromCSV(const string &line) { + stringstream ss(line); + string id, t, a, c, total, avail; + getline(ss, id, ','); + getline(ss, t, ','); + getline(ss, a, ','); + getline(ss, c, ','); + getline(ss, total, ','); + getline(ss, avail, ','); + Book b; + b = Book(stoi(id), trim(t), trim(a), trim(c), stoi(total)); + b.setTotalCopies(stoi(total)); + while (b.getAvailableCopies() > stoi(avail)) b.issueOne(); + return b; +} + +// ------------ Member ------------ +Member::Member() : id(-1) {} +Member::Member(int i, string n, string e) : id(i), name(move(n)), email(move(e)) {} + +int Member::getId() const { return id; } +string Member::getName() const { return name; } +string Member::getEmail() const { return email; } + +void Member::setName(const string &n) { name = n; } +void Member::setEmail(const string &e) { email = e; } + +string Member::toCSV() const { return to_string(id) + "," + name + "," + email; } + +Member Member::fromCSV(const string &line) { + stringstream ss(line); + string id, n, e; + getline(ss, id, ','); + getline(ss, n, ','); + getline(ss, e, ','); + return Member(stoi(id), trim(n), trim(e)); +} + +// ------------ Library ------------ +Library::Library() { loadAll(); } +Library::~Library() { saveAll(); } + +void Library::loadAll() { + ifstream fb(booksFile); + if (fb) { + string line; + while (getline(fb, line)) + if (!trim(line).empty()) { + Book b = Book::fromCSV(line); + books[b.getId()] = b; + nextBookId = max(nextBookId, b.getId() + 1); + } + } + + ifstream fm(membersFile); + if (fm) { + string line; + while (getline(fm, line)) + if (!trim(line).empty()) { + Member m = Member::fromCSV(line); + members[m.getId()] = m; + nextMemberId = max(nextMemberId, m.getId() + 1); + } + } +} + +void Library::saveAll() { + ofstream fb(booksFile); + for (auto &[_, b] : books) + fb << b.toCSV() << "\n"; + + ofstream fm(membersFile); + for (auto &[_, m] : members) + fm << m.toCSV() << "\n"; +} + +// Books +int Library::addBook(const string &t, const string &a, const string &c, int copies) { + int id = nextBookId++; + books[id] = Book(id, t, a, c, copies); + return id; +} + +void Library::updateBook(int id, const optional &t, const optional &a, + const optional &c, const optional &copies) { + auto it = books.find(id); + if (it == books.end()) throw runtime_error("Book not found"); + if (t) it->second.setTitle(*t); + if (a) it->second.setAuthor(*a); + if (c) it->second.setCategory(*c); + if (copies) it->second.setTotalCopies(*copies); +} + +void Library::deleteBook(int id) { + if (!books.count(id)) throw runtime_error("Book not found"); + books.erase(id); +} + +vector Library::listBooks() const { + vector v; + for (auto &[_, b] : books) v.push_back(b); + sort(v.begin(), v.end(), [](auto &x, auto &y){return x.getId() Library::searchByTitle(const string &q) const { + vector r; + for (auto &[_, b] : books) + if (lower(b.getTitle()).find(lower(q)) != string::npos) + r.push_back(b); + return r; +} + +vector Library::searchByAuthor(const string &q) const { + vector r; + for (auto &[_, b] : books) + if (lower(b.getAuthor()).find(lower(q)) != string::npos) + r.push_back(b); + return r; +} + +vector Library::searchByCategory(const string &q) const { + vector r; + for (auto &[_, b] : books) + if (lower(b.getCategory()).find(lower(q)) != string::npos) + r.push_back(b); + return r; +} + +// Members +int Library::addMember(const string &n, const string &e) { + int id = nextMemberId++; + members[id] = Member(id, n, e); + return id; +} + +void Library::updateMember(int id, const optional& n, const optional& e) { + auto it = members.find(id); + if (it == members.end()) throw runtime_error("Member not found"); + if (n) it->second.setName(*n); + if (e) it->second.setEmail(*e); +} + +void Library::deleteMember(int id) { + if (!members.count(id)) throw runtime_error("Member not found"); + members.erase(id); +} + +vector Library::listMembers() const { + vector v; + for (auto &[_, m] : members) v.push_back(m); + sort(v.begin(), v.end(), [](auto &x, auto &y){return x.getId() +using namespace std; + +// ---------------- Book ---------------- +class Book { + int id; + string title, author, category; + int totalCopies, availableCopies; + +public: + Book(); + Book(int id, string title, string author, string category, int copies); + + int getId() const; + string getTitle() const; + string getAuthor() const; + string getCategory() const; + int getTotalCopies() const; + int getAvailableCopies() const; + + void setTitle(const string&); + void setAuthor(const string&); + void setCategory(const string&); + void setTotalCopies(int); + + bool issueOne(); + bool returnOne(); + + string toCSV() const; + static Book fromCSV(const string&); +}; + +// ---------------- Member ---------------- +class Member { + int id; + string name, email; + +public: + Member(); + Member(int id, string name, string email); + + int getId() const; + string getName() const; + string getEmail() const; + + void setName(const string&); + void setEmail(const string&); + + string toCSV() const; + static Member fromCSV(const string&); +}; + +// ---------------- Transaction ---------------- +struct Transaction { + int memberId; + int bookId; + string date; + bool returned; +}; + +// ---------------- Library ---------------- +class Library { + unordered_map books; + unordered_map members; + vector transactions; + + int nextBookId = 1; + int nextMemberId = 1; + + const string booksFile = "books.csv"; + const string membersFile = "members.csv"; + const string txFile = "transactions.csv"; + + void loadAll(); + void saveAll(); + +public: + Library(); + ~Library(); + + // Books + int addBook(const string&, const string&, const string&, int); + void updateBook(int, const optional&, const optional&, const optional&, const optional&); + void deleteBook(int); + vector listBooks() const; + vector searchByTitle(const string&) const; + vector searchByAuthor(const string&) const; + vector searchByCategory(const string&) const; + + // Members + int addMember(const string&, const string&); + void updateMember(int, const optional&, const optional&); + void deleteMember(int); + vector listMembers() const; + + // Transactions + void issueBook(int memberId, int bookId); + void returnBook(int memberId, int bookId); +}; + +#endif diff --git a/Src/Library_Managment/main.cpp b/Src/Library_Managment/main.cpp new file mode 100644 index 0000000..413e840 --- /dev/null +++ b/Src/Library_Managment/main.cpp @@ -0,0 +1,69 @@ +#include "LibraryManagement.h" + +int main() { + Library lib; + + cout << "=== Library Management System ===\n"; + + while (true) { + cout << "\n1. Add Book\n2. List Books\n3. Add Member\n4. List Members\n" + "5. Issue Book\n6. Return Book\n7. Search Book by Title\n8. Exit\nChoice: "; + int ch; + if (!(cin >> ch)) break; + + try { + if (ch == 1) { + string t,a,c; int copies; + cout << "Title: "; cin.ignore(); getline(cin,t); + cout << "Author: "; getline(cin,a); + cout << "Category: "; getline(cin,c); + cout << "Copies: "; cin >> copies; + int id = lib.addBook(t,a,c,copies); + cout << "Book added with ID " << id << "\n"; + } + else if (ch == 2) { + for (auto &b : lib.listBooks()) + cout << b.getId() << ": " << b.getTitle() << " by " << b.getAuthor() + << " (" << b.getAvailableCopies() << "/" << b.getTotalCopies() << " available)\n"; + } + else if (ch == 3) { + string n,e; + cout << "Name: "; cin.ignore(); getline(cin,n); + cout << "Email: "; getline(cin,e); + int id = lib.addMember(n,e); + cout << "Member added with ID " << id << "\n"; + } + else if (ch == 4) { + for (auto &m : lib.listMembers()) + cout << m.getId() << ": " << m.getName() << " <" << m.getEmail() << ">\n"; + } + else if (ch == 5) { + int mid,bid; + cout << "Member ID: "; cin >> mid; + cout << "Book ID: "; cin >> bid; + lib.issueBook(mid,bid); + cout << "Book issued successfully\n"; + } + else if (ch == 6) { + int mid,bid; + cout << "Member ID: "; cin >> mid; + cout << "Book ID: "; cin >> bid; + lib.returnBook(mid,bid); + cout << "Book returned successfully\n"; + } + else if (ch == 7) { + string q; + cout << "Enter title search query: "; cin.ignore(); getline(cin,q); + auto res = lib.searchByTitle(q); + for (auto &b : res) + cout << b.getId() << ": " << b.getTitle() << " by " << b.getAuthor() << "\n"; + } + else if (ch == 8) break; + else cout << "Invalid choice.\n"; + } catch (const exception &e) { + cout << "Error: " << e.what() << "\n"; + } + } + cout << "Goodbye!\n"; + return 0; +}