DEV Community

Utkarsh Yadav
Utkarsh Yadav

Posted on

CLI Library Management-System C++

In this article, we will explore a simple Command Line Interface (CLI) program for a Library Management System. The program allows users to register books, register library members, and perform basic operations such as printing book data and saving data to files. The program is written in C++ and demonstrates the usage of classes, vectors, file handling, and user input.

Code Walkthrough

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <vector>

using namespace std;

class BookEntry
{
public:
    string bookName;
    string bookAuthor;
    string publisher;
    int ISBN;
    int edition;
    int publishYear;
    int numberOfBooks;
    vector<BookEntry> books; // Store multiple books

    void registerBook();
    void printData();
    void saveBookDataToFile(const string &filename);
};

class MemberEntry
{
public:
    string memberName;
    string memberAddress;
    string memberEmail;
    int memberID;

    void registerMember();
    void saveMemberDataToFile(const string &filename);
    bool isMemberExist(const string &filename);
};

// ...
Enter fullscreen mode Exit fullscreen mode

The code starts by including necessary libraries (iostream, fstream, string, iomanip, and vector) and using the std namespace. Then, it defines two classes: BookEntry and MemberEntry. These classes encapsulate the functionality related to book and member management, respectively.

The BookEntry class has member variables representing book details such as name, author, publisher, ISBN, edition, publish year, and the number of books. It also includes a vector named books to store multiple book entries. The class provides member functions to register a book, print book data, and save book data to a file.

The MemberEntry class contains member variables for member details like name, address, email, and member ID. It has member functions to register a member, save member data to a file, and check if a member already exists.

Now, let's take a look at the member function implementations of BookEntry:

void BookEntry::registerBook()
{
    cout << "Enter the number of Books this time:\n";
    cin >> numberOfBooks;

    for (int i = 0; i < numberOfBooks; ++i)
    {
        cout << "===============================\n";
        cout << "     CLI for Book Entry\n";
        cout << "===============================\n";
        cout << "Enter the Name of the Book: ";
        cin >> bookName;
        cout << "Enter the Author of the Book: ";
        cin >> bookAuthor;
        cout << "Enter the Publisher: ";
        cin >> publisher;
        cout << "Enter the ISBN number of the Book: ";
        cin >> ISBN;
        cout << "Enter the Edition (numbers only): ";
        cin >> edition;

        BookEntry book;
        book.bookName = bookName;
        book.bookAuthor = bookAuthor;
        book.publisher = publisher;
        book.ISBN = ISBN;
        book.edition = edition;
        books.push_back(book);
    }
}

void BookEntry::printData()
{
    cout << "=========================================\n";
    cout << "           Books in Library\n";
    cout << "=========================================\n";

    if (books.empty())
    {
        cout << "No books available.\n";
        return;
    }

    cout << left << setw(6) << "S.No"
         << setw(25) << "Title"
         << setw(25) << "Author"
         << setw(25) << "Publication"
         << setw(15) << "ISBN"
         << setw(10) << "Edition"
         << "\n";

    for (int i = 0; i < books.size(); i++)
    {
        if (i >= books.size() - numberOfBooks)
            cout << left << setw(6) << i + 1 << "*"
                 << setw(25) << books[i].bookName
                 << setw(25) << books[i].bookAuthor
                 << setw(25) << books[i].publisher
                 << setw(15) << books[i].ISBN
                 << setw(10) << books[i].edition
                 << "\n";
        else
            cout << left << setw(6) << i + 1
                 << setw(25) << books[i].bookName
                 << setw(25) << books[i].bookAuthor
                 << setw(25) << books[i].publisher
                 << setw(15) << books[i].ISBN
                 << setw(10) << books[i].edition
                 << "\n";
    }
}

void BookEntry::saveBookDataToFile(const string &filename)
{
    ofstream outputFile(filename);

    if (!outputFile.is_open())
    {
        cout << "Failed to open the file: " << filename << endl;
        return;
    }

    outputFile << "Books in Library\n";
    outputFile << "=========================================\n";
    outputFile << left << setw(6) << "S.No"
               << setw(25) << "Title"
               << setw(25) << "Author"
               << setw(25) << "Publication"
               << setw(15) << "ISBN"
               << setw(10) << "Edition"
               << "\n";

    for (int i = 0; i < books.size(); i++)
    {
        if (i >= books.size() - numberOfBooks)
            outputFile << left << setw(6) << i + 1 << "*"
                       << setw(25) << books[i].bookName
                       << setw(25) << books[i].bookAuthor
                       << setw(25) << books[i].publisher
                       << setw(15) << books[i].ISBN
                       << setw(10) << books[i].edition
                       << "\n";
        else
            outputFile << left << setw(6) << i + 1
                       << setw(25) << books[i].bookName
                       << setw(25) << books[i].bookAuthor
                       << setw(25) << books[i].publisher
                       << setw(15) << books[i].ISBN
                       << setw(10) << books[i].edition
                       << "\n";
    }

    cout << "Book data saved to file: " << filename << endl;

    outputFile.close();
}
Enter fullscreen mode Exit fullscreen mode

The registerBook() function allows the user to register multiple books. It prompts the user to enter the number of books to register and then iterates that many times to collect book details such as name, author, publisher, ISBN, and edition. For each book, a BookEntry object is created and its member variables are set accordingly. The object is then added to the books vector.

The printData() function displays the book data stored in the books vector. It first checks if the vector is empty and prints a message if there are no books. If books are available, it formats and prints the book details in a tabular format.

The saveBookDataToFile() function saves the book data to a file. It opens the specified file in output mode (ofstream) and checks if the file is successfully opened. If the file fails to open, an error message is displayed. The function then writes the book data to the file in a formatted manner. It first writes the table header, followed by the book details. For the last numberOfBooks books in the books vector, an asterisk (*) is added to indicate their availability. Finally, it displays a success message and closes the file.

Now, let's move on to the member function implementations of MemberEntry:

void MemberEntry::registerMember()
{
    cout << "===============================\n";
    cout << "     CLI for Member Entry\n";
    cout << "===============================\n";
    cout << "Enter the Name of the Member: ";
    cin >> memberName;
    cout << "Enter the Address of the Member: ";
    cin >> memberAddress;
    cout << "Enter the Email of the Member: ";
    cin >> memberEmail;
    cout << "Enter the Member ID: ";
    cin >> memberID;
}

void MemberEntry::saveMemberDataToFile(const string &filename)
{
    ofstream outputFile(filename, ios::app);

    if (!outputFile.is_open())
    {
        cout << "Failed to open the file: " << filename << endl;
        return;
    }

    outputFile << "Member Details\n";
    outputFile << "=========================================\n";
    outputFile << "Name: " << memberName << endl;
    outputFile << "Address: " << memberAddress << endl;
    outputFile << "Email: " << memberEmail << endl;
    outputFile << "Member ID: " << memberID << endl;
    outputFile << "--------------------------------------" << endl;

    cout << "Member data saved to file: " << filename << endl;

    outputFile.close();
}

bool MemberEntry::isMemberExist(const string &filename)
{
    ifstream inputFile(filename);

    if (!inputFile.is_open())
    {
        cout << "Failed to open the file: " << filename << endl;
        return false;
    }

    string line;
    string searchName = "Name: " + memberName;
    string searchEmail = "Email: " + memberEmail;

    while (getline(inputFile, line))
    {
        if (line.find(searchName) != string::npos || line.find(searchEmail) != string::npos)
        {
            cout << "Member already exists.\n";
            inputFile.close();
            return true;
        }
    }

    inputFile.close();
    return false;
}
Enter fullscreen mode Exit fullscreen mode

The registerMember() function collects member details from the user. It prompts the user to enter the member's name, address, email, and ID. The entered values are stored in the corresponding member variables.

The saveMemberDataToFile() function saves the member data to a file. It opens the specified file in append mode (ofstream with ios::app flag) and checks if the file is successfully opened. If the file fails to open, an error message is displayed. The function then writes the member details to the file, including the member's name, address, email, and ID. The data is formatted with appropriate labels. Finally, it displays a success message and closes the file.

The isMemberExist() function checks if a member already exists in the given file. It opens the file in input mode (ifstream) and checks if the file is successfully opened. If the file fails to open, an error message is displayed. The function then reads the file line by line and compares each line with the search criteria (name and email) to determine if a matching member already exists. If a match is found, a message is displayed, and the function returns true to indicate that the member exists. If no match is found, the function returns false.

Next, let's examine the Options class and its options() member function:

class Options : public BookEntry, public MemberEntry
{
public:
    void options();
};

void Options::options()
{
    char opts;
    bool running = true;

    while (running)
    {
        cout << "===============================\n";
        cout << "      CLI for Options\n";
        cout << "===============================\n";
        cout << "1. To make an Entry of Book\n";
        cout << "2. To Issue Book \n";
        cout << "3. Register a Member \n";
        cout << "Press Esc key to exit\n";
        cin >> opts;

        switch (opts)
        {
        case '1':
            registerBook();
            printData();
            saveBookDataToFile("book_data.txt");
            break;
        case '2':
            cout << "Issuing the book...\n";
            break;
        case '3':
            registerMember();
            if (!isMemberExist("member_data.txt"))
                saveMemberDataToFile("member_data.txt");
            break;
        case 27:
            running = false;
            break;
        default:
            cout << "Invalid option\n";
            break;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The Options class inherits from both BookEntry and MemberEntry classes. It provides the options() member function to display a menu and handle user input for different operations. Within the options() function, a while loop runs until the user chooses to exit by pressing the Esc key. In each iteration, the menu is displayed, and the user's choice is read into the opts variable.

Based on the user's input, the switch statement performs different actions:

  • If the user chooses '1', it calls the registerBook() function to register books, then prints the book data using printData(), and finally saves the book data to a file using saveBookDataToFile().

  • If the user chooses '2', a placeholder message is displayed for issuing a book (you can customize this functionality).

  • If the user chooses '3', it calls the registerMember() function to register a member. Before saving the member data, it checks if the member already exists using isMemberExist(). If the member does not exist, the member data is saved to a file using saveMemberDataToFile().

  • If the user presses the Esc key (27), the loop is terminated, and the program exits.

  • If the user inputs any other character, an "Invalid option" message is displayed.

This implementation allows users to interact with the CLI and perform operations such as registering books and members, and saving the data to files.

Final Code

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <vector>

using namespace std;

class BookEntry
{
public:
    string bookName;
    string bookAuthor;
    string publisher;
    int ISBN;
    int edition;
    int publishYear;
    int numberOfBooks;
    vector<BookEntry> books; // Store multiple books

    void registerBook();
    void printData();
    void saveBookDataToFile(const string &filename);
};

class MemberEntry
{
public:
    string memberName;
    string memberAddress;
    string memberEmail;
    int memberID;

    void registerMember();
    void saveMemberDataToFile(const string &filename);
    bool isMemberExist(const string &filename);
};

void BookEntry::registerBook()
{
    cout << "Enter the number of Books this time:\n";
    cin >> numberOfBooks;

    for (int i = 0; i < numberOfBooks; ++i)
    {
        cout << "===============================\n";
        cout << "     CLI for Book Entry\n";
        cout << "===============================\n";
        cout << "Enter the Name of the Book: ";
        cin >> bookName;
        cout << "Enter the Author of the Book: ";
        cin >> bookAuthor;
        cout << "Enter the Publisher: ";
        cin >> publisher;
        cout << "Enter the ISBN number of the Book: ";
        cin >> ISBN;
        cout << "Enter the Edition (numbers only): ";
        cin >> edition;

        // Create a book object and add it to the vector of books
        BookEntry book;
        book.bookName = bookName;
        book.bookAuthor = bookAuthor;
        book.publisher = publisher;
        book.ISBN = ISBN;
        book.edition = edition;
        books.push_back(book);
    }
}

void BookEntry::printData()
{
    cout << "=========================================\n";
    cout << "           Books in Library\n";
    cout << "=========================================\n";

    if (books.empty())
    {
        cout << "No books available.\n";
        return;
    }

    cout << left << setw(6) << "S.No"
         << setw(25) << "Title"
         << setw(25) << "Author"
         << setw(25) << "Publication"
         << setw(15) << "ISBN"
         << setw(10) << "Edition"
         << "\n";

    for (int i = 0; i < books.size(); i++)
    {
        if (i >= books.size() - numberOfBooks)
            cout << left << setw(6) << i + 1 << "*"
                 << setw(25) << books[i].bookName
                 << setw(25) << books[i].bookAuthor
                 << setw(25) << books[i].publisher
                 << setw(15) << books[i].ISBN
                 << setw(10) << books[i].edition
                 << "\n";
        else
            cout << left << setw(6) << i + 1
                 << setw(25) << books[i].bookName
                 << setw(25) << books[i].bookAuthor
                 << setw(25) << books[i].publisher
                 << setw(15) << books[i].ISBN
                 << setw(10) << books[i].edition
                 << "\n";
    }
}

void BookEntry::saveBookDataToFile(const string &filename)
{
    ofstream outputFile(filename);

    if (!outputFile.is_open())
    {
        cout << "Failed to open the file: " << filename << endl;
        return;
    }

    outputFile << "Books in Library\n";
    outputFile << "=========================================\n";
    outputFile << left << setw(6) << "S.No"
               << setw(25) << "Title"
               << setw(25) << "Author"
               << setw(25) << "Publication"
               << setw(15) << "ISBN"
               << setw(10) << "Edition"
               << "\n";

    for (int i = 0; i < books.size(); i++)
    {
        if (i >= books.size() - numberOfBooks)
            outputFile << left << setw(6) << i + 1 << "*"
                       << setw(25) << books[i].bookName
                       << setw(25) << books[i].bookAuthor
                       << setw(25) << books[i].publisher
                       << setw(15) << books[i].ISBN
                       << setw(10) << books[i].edition
                       << "\n";
        else
            outputFile << left << setw(6) << i + 1
                       << setw(25) << books[i].bookName
                       << setw(25) << books[i].bookAuthor
                       << setw(25) << books[i].publisher
                       << setw(15) << books[i].ISBN
                       << setw(10) << books[i].edition
                       << "\n";
    }

    cout << "Book data saved to file: " << filename << endl;

    outputFile.close();
}

void MemberEntry::registerMember()
{
    cout << "===============================\n";
    cout << "     CLI for Member Entry\n";
    cout << "===============================\n";
    cout << "Enter the Name of the Member: ";
    cin >> memberName;
    cout << "Enter the Address of the Member: ";
    cin >> memberAddress;
    cout << "Enter the Email of the Member: ";
    cin >> memberEmail;
    cout << "Enter the Member ID: ";
    cin >> memberID;
}

void MemberEntry::saveMemberDataToFile(const string &filename)
{
    ofstream outputFile(filename, ios::app);

    if (!outputFile.is_open())
    {
        cout << "Failed to open the file: " << filename << endl;
        return;
    }

    outputFile << "Member Details\n";
    outputFile << "=========================================\n";
    outputFile << "Name: " << memberName << endl;
    outputFile << "Address: " << memberAddress << endl;
    outputFile << "Email: " << memberEmail << endl;
    outputFile << "Member ID: " << memberID << endl;
    outputFile << "--------------------------------------" << endl;

    cout << "Member data saved to file: " << filename << endl;

    outputFile.close();
}

bool MemberEntry::isMemberExist(const string &filename)
{
    ifstream inputFile(filename);

    if (!inputFile.is_open())
    {
        cout << "Failed to open the file: " << filename << endl;
        return false;
    }

    string line;
    string searchName = "Name: " + memberName;
    string searchEmail = "Email: " + memberEmail;

    while (getline(inputFile, line))
    {
        if (line.find(searchName) != string::npos || line.find(searchEmail) != string::npos)
        {
            cout << "Member already exists.\n";
            inputFile.close();
            return true;
        }
    }

    inputFile.close();
    return false;
}

class Options : public BookEntry, public MemberEntry
{
public:
    void options();
};

void Options::options()
{
    char opts; // Change the data type to char
    bool running = true;

    while (running)
    {
        cout << "===============================\n";
        cout << "      CLI for Options\n";
        cout << "===============================\n";
        cout << "1. To make an Entry of Book\n";
        cout << "2. To Issue Book \n";
        cout << "3. Register a Member \n";
        cout << "Press Esc key to exit\n";
        cin >> opts;

        switch (opts)
        {
        case '1': 
            registerBook();
            printData();
            saveBookDataToFile("book_data.txt");
            break;
        case '2':
            cout << "Issuing the book...\n";
            break;
        case '3':
            registerMember();
            if (!isMemberExist("member_data.txt"))
                saveMemberDataToFile("member_data.txt");
            break;
        case 27:
            running = false;
            break;
        default:
            cout << "Invalid option\n";
            break;
        }
    }
}

int main()
{
    Options op;
    op.options();

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
pauljlucas profile image
Paul J. Lucas

This isn't a command-line interface. It's a text-based interface. A CLI is literally and only for the command line: the command you type, possibly with options, at the shell prompt. Here is a post about an actual CLI.

Naming aside, your code isn't production code. You never just read things like integers from cin that has no real error detection. What happens if you type a string where an integer is expected? To be a real program, you always have to read only strings from cin then parse the strings into integers so that you can detect non-integers and print appropriate error messages.