×

Search anything:

Bank Management System in C++ [Project with source code]

C++

Binary Tree book by OpenGenus

Open-Source Internship opportunity by OpenGenus for programmers. Apply now.

Table of contents:

  1. Introduction
  2. Step 1: Create Database Class
  3. Step 2: Define Transaction Class
  4. Step 3: Create Bank Account Class
  5. Step 4: Define Bank Manager Class
  6. Step 5: Finalize The Banking Simulation
  7. Step 6: Testing our Implementation
  8. Conclusion

Reading time: 25 minutes

Introduction

In this article at OpenGenus, we will cover how to create a bank management system in C++ programming language. A bank management system can be used to manage a bank account, withdraw and deposit funds, and check the account balance.

Specifically, our system will support user login with a username and password as well as the ability to save data of an account and its banking information.

What are the requirements for this program?

System Requirements

  1. C++ compiler
  2. Command Prompt or Terminal to run the program

Technical Requirements

  1. Knowledge of C++ OOP principles and classes

Project Requirements

  1. File handling: reading and writing data to a file will be utilized to save account login data.
  2. Banking functionality: deposits, withdrawals, and other banking operations to be performed by the user.
  3. User input/output: input will be gathered for account creation and navigation of the banking program. Output in terminal will be used to display instructions to the user or account data.

What classes will be utilized?

This banking program utilizes a multitude of classes that each have their own responsibilities:

  1. Database: responsible for saving and loading user data from a text file. Overall, this class will help manage user data and functions involving data access such as user login, user creation, and user deletion.
  2. Transaction: represents a specific transaction along with its type and amount.
  3. BankAccount: represents a bank account and provides functionality for managing banking transactions.
  4. BankManager: manages banking manager accounts by providing login functionality and the ability to view user data.

Program Design

Each class represents and organizes the different responsibilities within the banking system. Through keeping an organized structure, the code can be easily updated and maintained. All user and manager account data are stored in users.txt and managers.txt respectively while both UserManager and BankManager provide login abilities for these accounts. The main function takes care of user interactions and ensures all users can easily access and use their bank account to perform their banking needs.

Step 1: Create Database Class

For our users and their banking data to be stored, we will define a database class that takes care of all operations involving saving and loading data from a file, user login, and the creation and deletion of users. Our file users.txt will store all users who have opened an account and their corresponding password. Because their login data will be saved in the system, they can log back in at any time:

class Database {
public:
    Database() {
        loadUsersFromFile();
        loadManagersFromFile();
    }

    void saveUsersToFile() { // Save username and password to users.txt
        ofstream userFile("users.txt");

        for (const auto &user : users) {l
            userFile << user.first << " " << user.second.first << " " << user.second.second << endl;
        }
        userFile.close();
    }

    bool loadUsersFromFile() {
        ifstream userFile("users.txt");
        if (!userFile) {
            return false;
        }

        string line;
        while (getline(userFile, line)) {
            istringstream iss(line);
            string username, password;
            if (iss >> username >> password) {
                users[username].first = password;
            }
        }

        userFile.close();
        return true;
    }

    bool loadManagersFromFile() {
        ifstream managerFile("managers.txt");
        if (!managerFile) {
            return false;
        }

        string line;
        while (getline(managerFile, line)) {
            istringstream iss(line);
            string username, password;
            if (iss >> username >> password) {
                managers[username] = password;
            }
        }
        managerFile.close();
        return true;
    }

    void createUser(const string &username, const string &password) {
        users[username] = make_pair(password, 0.0);
        saveUsersToFile();
        cout << "User created successfully." << endl;
    }

    void deleteUser(const string &username) {
        users.erase(username);
    }

    bool login() {
        string username, password;
        cout << "Enter username: ";
        cin >> username;

        if (users.find(username) != users.end()) {
            cout << "Enter password: ";
            cin >> password;

            if (users[username].first == password) {
                return true;
            }
        }
        cout << "Incorrect username or password. Try again." << endl;
        return false;
    }   

private:
    unordered_map<string, pair<string, double>> users;
    unordered_map<string, string> managers;
};

In the above code, we have defined saveUsersToFile which saves all usernames, passwords, and their account balance to users.txt.

loadUsersFromFile reads login information from users.txt and places it inside an unordered map of users. loadManagersFromFile reads manager login information from managers.txt and places it inside an unordered map of managers.

createUser receives a username and password as input and saves them both to the database. This function initalizes the users account balance to 0 and saves it to file.

deleteUser removes a provided user from the database. This method will be utilized when a user requests to close their account, which we will cover later in the article.

The login function prompts the user to enter a username and password and checks if their user data is in the system. If not, it informs the user that their login information is incorrect and allows them to try again. If both their user and password are correct, they will be successfully logged into their account.

Step 2: Define Transaction Class

To manage transactions made by a user, we will define a transaction class that keeps track of which transaction was made and how much money was transacted:

class Transaction {
public:
    string type; // Type of transaction
    double amount; // Amount transacted

    Transaction(const string &t, double a) : type(t), amount(a) {}
};

Step 3: Create Bank Account Class

We must create an outline for managing banking accounts within our bank management system. In addition to defining the structure of the bank accounts, we will also define all available banking options given to a user once they log in. These options include withdrawal, deposit, closing their account, and printing their account summary. As long as their account is open, the user will have the ability to perform all available actions:

class BankAccount {
public:
    BankAccount(const string &username, Database &db) : username(username), open(true), balance(0), database(db) {
        // Read account balance from file users.txt
        ifstream file("users.txt");
        string line;
        while(getline(file, line)) {
            istringstream iss(line);
            string storedUsername, storedPassword;
            double storedBalance;
            if (iss >> storedUsername >> storedPassword >> storedBalance) {
                if (storedUsername == username) {
                    balance = storedBalance;
                    break;
                }
            }
        }
    }

    void Withdraw(double amount) {
        if (open && amount <= balance && amount > 0) {
            balance -= amount;
            transactions.emplace_back("Withdrawal", amount);
            cout << "Successfully withdrew $" << amount << " from your account." << endl;
            cout << "Your new balance is: " << balance << endl;
            updateBalanceInFile();
        } else {
            cout << "Invalid amount provided or account is deactivated. Contact support for further assistance. " << endl;
        }
    }

    void Deposit(double amount) {
        if (open && amount > 0) {
            balance += amount;
            transactions.emplace_back("Deposit", amount);
            cout << "Successfully deposited $" << amount << " to your account." << endl;
            cout << "Your new balance is: " << balance << endl;
            updateBalanceInFile();
        } else {
            cout << "Invalid amount provided or account is deactivated. Contact support for further assistance. " << endl;
        }
    }

    void PrintAccountSummary() {
        cout << "Account Holder: " << username << endl;
        cout << "Balance: $" << balance << endl;
        cout << "Transactions:" << endl;
        for (const Transaction &transaction : transactions) {
            cout << transaction.type << ", Amount: $" << transaction.amount << endl;
        }
        cout << " " << endl;
    }      

    void CloseAccount(Database &database) {
        open = false;
        database.deleteUser(username);
        database.saveUsersToFile();
        cout << "Your account has been closed." << endl;
    } 
    
    void setUsername(const string &newUsername) {
        username = newUsername;
    }

    void updateBalanceInFile() {
    ifstream inputFile("users.txt");
    ofstream outputFile("temp.txt");

    string line;
    while (getline(inputFile, line)) {
        istringstream iss(line);
        string storedUsername, storedPassword;
        double storedBalance;

        if (iss >> storedUsername >> storedPassword >> storedBalance) {
            if (storedUsername == username) {
                outputFile << username << " " << storedPassword << " " << balance << endl;
            } else {
                outputFile << line << endl;
            }
        }
    }

    inputFile.close();
    outputFile.close();

    remove("users.txt");
    rename("temp.txt", "users.txt");
    }

private:
    string username;
    bool open;
    double balance;
    vector<Transaction> transactions;
    Database &database;
};

If an existing user logs in, their account balance from previous transactions will be read and retrieved from 'users.txt'. Otherwise, their balance is initialized as 0.

Each time a user performs a banking transaction, their balance within 'users.txt' is updated with updateBalanceInFile.

Withdraw removes a specified amount of funds from the user's account given that they have enough money to do so.

Deposit allows the user to add a specified amount of money to their account. The amount is added to their total account balance if their account is currently open. Otherwise, the user is notified of the error.

PrintAccountSummary displays the user's complete history of transactions as well as their current account balance.

CloseAccount closes a created account if desired by the user and deletes their login data from the database.

setUsername updates the bank account with the username chosen.

Step 4: Define Bank Manager Class

To allow bank managers to log in to the system and check user data, we will provide a specialized class for managers specifically.

For this to work, you must create your own managers.txt file and place both your username and password inside the file separated by a space. The program does not provide the user with the ability to create a manager account since anyone would be able to do that and we want to provide security to our users:

class BankManager {
public:
    BankManager() {
        loadManagersFromFile();
    }
    bool login() {
        string username, password;
        cout << "Enter username: ";
        cin >> username;
        if (managers.find(username) != managers.end()) {
            cout << "Enter password: ";
            cin >> password;

            if (managers[username] == password) {
                return true;
            }
        }
        cout << "Incorrect login. Please try again. " << endl;
        return false;
    }

    bool loadManagersFromFile() {
        ifstream managerFile("managers.txt");
        if (!managerFile) {
            return false;
        }

        string line;
        while (getline(managerFile, line)) {
            istringstream iss(line);
            string username, password;
            if (iss >> username >> password) {
                managers[username] = password;
            }
        }
        managerFile.close();
        return true;
    }   

private:
    unordered_map<string, string> managers; 
};

login prompts the manager for a username and password and checks if they match what is located within managers.txt. When successful, the manager will be logged into their special account.

loadManagersFromFile reads login data from managers.txt and places this data inside an unordered map of managers.

Step 5: Finalize The Banking Simulation

To complete our banking simulation, we must ensure that the user can choose between different banking and account options. To do so, we will display these choices as a list and prompt the user to enter the number corresponding with the choice they'd like to make:

int main() {
    Database database;
    BankManager manager;
    string username, password;
    BankAccount acc("", database);
    int choice;
    int bankingOption;
    double withdrawAmt;
    double depositAmt;
    bool loggedIn = false;
    bool managerLoggedIn = false;
    while (true) {
        if (!loggedIn) {
            cout << "1. Login\n2. Create Account\n3. Manager Login\n4. Exit\n";
            cin >> choice;

            if (choice == 1) {
                if (database.login()) {
                    loggedIn = true;
                    username = username;
                    acc.setUsername(username);
                }   
            } else if (choice == 2) {
                string newUsername, password;
                cout << "Enter new username: ";
                cin >> newUsername;
                cout << "Enter password: ";
                cin >> password;
                database.createUser(newUsername, password);
                username = newUsername;
                acc.setUsername(username);
            } else if (choice == 3) {
                if (manager.login()) {
                    loggedIn = true;
                    managerLoggedIn = true;
                    // Manager login options
                    cout << "Manager Options\n";
                    cout << "1. Get List of Users and Account Details\n2. Logout\n";
                    cin >> bankingOption;
                    if (bankingOption == 1) {
                        ifstream userFile("users.txt");
                        if (userFile.is_open()) {
                            string line;
                            while (getline(userFile, line)) {
                                cout << line << endl;
                            }
                            userFile.close();
                        }
                    }
                    if (bankingOption == 2) {
                        managerLoggedIn = false;
                        loggedIn = false;
                    }
                }
            } else if (choice == 4) {
                break; // Exit the program
            }
        } else {
            if (managerLoggedIn) {
                cout << "Manager Options\n";
                cout << "1. Get List of Users and Account Details\n2. Logout\n";
                cin >> bankingOption;
                if (bankingOption == 1) {
                    ifstream userFile("users.txt");
                    if (userFile.is_open()) {
                        string line;
                        while (getline(userFile, line)) {
                            cout << line << endl;
                        }
                        userFile.close();
                    }
                }
                if (bankingOption == 2) {
                    loggedIn = false;
                }
            } else {
                // Account login options
                cout << "User Options:\n";
                cout << "1. Withdraw\n2. Deposit\n3. Get Account Summary\n4. Close Account\n5. Logout\n";
                cin >> bankingOption;
                if (bankingOption == 1) {
                    cout << "Please enter withdrawal amount: ";
                    cin >> withdrawAmt;
                    acc.Withdraw(withdrawAmt);
                } else if (bankingOption == 2) {
                    cout << "Please enter deposit amount: ";
                    cin >> depositAmt;
                    acc.Deposit(depositAmt);
                } else if (bankingOption == 3) {
                    acc.PrintAccountSummary();
                } else if (bankingOption == 4) {
                    acc.CloseAccount(database);
                    loggedIn = false;
                } else if (bankingOption == 5) {
                    loggedIn = false;
                }
            }
        }
    }
    return 0;
}

To use the banking simulation, the user must:

  1. Create an account and then login to that account.
  2. Once logged in, you will be presented with all banking and account options available. Type and enter the corresponding number to the action you want to perform.

Step 6: Testing our Implementation

To test our implementation, you must first navigate to the correct directory where the file is located. Once you are in the correct directory, compile the code. This can be done using Terminal, Command Prompt, Ubuntu, etc. To run my code, I used Ubuntu and ran the following command:
g++ bank.cpp -o bank

Then, to run the code I used the command:
./bank

When run correctly, the output should look like this:

Screenshot-2023-08-18-141635

To move forward with testing our implementation, we must enter the number corresponding to the choice we want to make. In this case, we would like to create an account since we have yet to make one. Type 2 into the terminal and press enter.

Next, it will prompt you to enter a new username. This can be any name of your choice! Once that is complete, enter a password to complete your account creation.

Screenshot-2023-08-18-142020

Once your account is created, enter 1 to fill in your login information. When successfully logged in, you will be prompted with five choices:

Screenshot-2023-08-18-142148

Go through and test all five features to ensure that your banking system works! You can withdraw and deposit funds into your account, get your account summary, close your account**, or log out.

Let's say I create two accounts: jessica 10 and testing 123. The contents of users.txt would look like:

username password accountbalance
testing 123 0
jessica 10 0

If I were to deposit $1000 dollars to my 'testing' account, the contents of users.txt would change to:

testing 123 1000
jessica 10 0

If I wanted to make a manager for the banking system, I would manually add their account details to managers.txt:

managerusername managerpassword
managerjess 10 

Conclusion

Overall, a text-based bank management system is the simplest way to handle account creation and basic banking transactions. But, there are certainly more appealing and efficient methods of implementing such a system:

  • Mobile Apps: Apps are commonly used by banking corporations due to ease and convenience of use. Users can simply download the app on their mobile devices and access their bank through the click of a button.
  • Web-based Interface: A web-based banking system is also often used by banks to allow users to access their accounts through their browsers. This approach can be even more convenient since it is not required for the user to download anything to use the interface.

Here is the complete code for the bank management system in C++:

#include <iostream>
#include <fstream>
#include <string>
#include <unordered_map>
#include <sstream>
#include <vector>
#include <random> 
#include <set> 
using namespace std;

class Database {
public:
    Database() {
        loadUsersFromFile();
        loadManagersFromFile();
    }

    void saveUsersToFile() { // Save username and password to users.txt
        ofstream userFile("users.txt");

        for (const auto &user : users) {
            userFile << user.first << " " << user.second.first << " " << user.second.second << endl;
        }
        userFile.close();
    }

    bool loadUsersFromFile() {
        ifstream userFile("users.txt");
        if (!userFile) {
            return false;
        }

        string line;
        while (getline(userFile, line)) {
            istringstream iss(line);
            string username, password;
            if (iss >> username >> password) {
                users[username].first = password;
            }
        }

        userFile.close();
        return true;
    }

    bool loadManagersFromFile() {
        ifstream managerFile("managers.txt");
        if (!managerFile) {
            return false;
        }

        string line;
        while (getline(managerFile, line)) {
            istringstream iss(line);
            string username, password;
            if (iss >> username >> password) {
                managers[username] = password;
            }
        }
        managerFile.close();
        return true;
    }

    void createUser(const string &username, const string &password) {
        users[username] = make_pair(password, 0.0);
        saveUsersToFile();
        cout << "User created successfully." << endl;
    }

    void deleteUser(const string &username) {
        users.erase(username);
    }

    bool login() {
        string username, password;
        cout << "Enter username: ";
        cin >> username;

        if (users.find(username) != users.end()) {
            cout << "Enter password: ";
            cin >> password;

            if (users[username].first == password) {
                return true;
            }
        }
        cout << "Incorrect username or password. Try again." << endl;
        return false;
    }   

private:
    unordered_map<string, pair<string, double>> users;
    unordered_map<string, string> managers;
};

class Transaction {
public:
    string type; // Type of transaction
    double amount; // Amount transacted

    Transaction(const string &t, double a) : type(t), amount(a) {}
};


class BankAccount {
public:
    BankAccount(const string &username, Database &db) : username(username), open(true), balance(0), database(db) {
        // Read account balance from file users.txt
        ifstream file("users.txt");
        string line;
        while(getline(file, line)) {
            istringstream iss(line);
            string storedUsername, storedPassword;
            double storedBalance;
            if (iss >> storedUsername >> storedPassword >> storedBalance) {
                if (storedUsername == username) {
                    balance = storedBalance;
                    break;
                }
            }
        }
    }

    void Withdraw(double amount) {
        if (open && amount <= balance && amount > 0) {
            balance -= amount;
            transactions.emplace_back("Withdrawal", amount);
            cout << "Successfully withdrew $" << amount << " from your account." << endl;
            cout << "Your new balance is: " << balance << endl;
            updateBalanceInFile();
        } else {
            cout << "Invalid amount provided or account is deactivated. Contact support for further assistance. " << endl;
        }
    }

    void Deposit(double amount) {
        if (open && amount > 0) {
            balance += amount;
            transactions.emplace_back("Deposit", amount);
            cout << "Successfully deposited $" << amount << " to your account." << endl;
            cout << "Your new balance is: " << balance << endl;
            updateBalanceInFile();
        } else {
            cout << "Invalid amount provided or account is deactivated. Contact support for further assistance. " << endl;
        }
    }

    void PrintAccountSummary() {
        cout << "Account Holder: " << username << endl;
        cout << "Balance: $" << balance << endl;
        cout << "Transactions:" << endl;
        for (const Transaction &transaction : transactions) {
            cout << transaction.type << ", Amount: $" << transaction.amount << endl;
        }
        cout << " " << endl;
    }      

    void CloseAccount(Database &database) {
        open = false;
        database.deleteUser(username);
        database.saveUsersToFile();
        cout << "Your account has been closed." << endl;
    } 
    
    void setUsername(const string &newUsername) {
        username = newUsername;
    }

    void updateBalanceInFile() {
    ifstream inputFile("users.txt");
    ofstream outputFile("temp.txt");

    string line;
    while (getline(inputFile, line)) {
        istringstream iss(line);
        string storedUsername, storedPassword;
        double storedBalance;

        if (iss >> storedUsername >> storedPassword >> storedBalance) {
            if (storedUsername == username) {
                outputFile << username << " " << storedPassword << " " << balance << endl;
            } else {
                outputFile << line << endl;
            }
        }
    }

    inputFile.close();
    outputFile.close();
    
    remove("users.txt");
    rename("temp.txt", "users.txt");
    }

private:
    string username;
    bool open;
    double balance;
    vector<Transaction> transactions;
    Database &database;
};

class BankManager {
public:
    BankManager() {
        loadManagersFromFile();
    }
    bool login() {
        string username, password;
        cout << "Enter username: ";
        cin >> username;
        if (managers.find(username) != managers.end()) {
            cout << "Enter password: ";
            cin >> password;

            if (managers[username] == password) {
                return true;
            }
        }
        cout << "Incorrect login. Please try again. " << endl;
        return false;
    }

    bool loadManagersFromFile() {
        ifstream managerFile("managers.txt");
        if (!managerFile) {
            return false;
        }

        string line;
        while (getline(managerFile, line)) {
            istringstream iss(line);
            string username, password;
            if (iss >> username >> password) {
                managers[username] = password;
            }
        }
        managerFile.close();
        return true;
    }   

private:
    unordered_map<string, string> managers; 
};

int main() {
    Database database;
    BankManager manager;
    string username, password;
    double initBalance;
    BankAccount acc("", database);
    int choice;
    int bankingOption;
    double withdrawAmt;
    double depositAmt;
    bool loggedIn = false;
    bool managerLoggedIn = false;
    while (true) {
        if (!loggedIn) {
            cout << "1. Login\n2. Create Account\n3. Manager Login\n4. Exit\n";
            cin >> choice;

            if (choice == 1) {
                if (database.login()) {
                    loggedIn = true;
                    username = username;
                    acc.setUsername(username);
                }   
            } else if (choice == 2) {
                string newUsername, password;
                cout << "Enter new username: ";
                cin >> newUsername;
                cout << "Enter password: ";
                cin >> password;
                database.createUser(newUsername, password);
                username = newUsername;
                acc.setUsername(username);
            } else if (choice == 3) {
                if (manager.login()) {
                    loggedIn = true;
                    managerLoggedIn = true;
                    // Manager login options
                    cout << "Manager Options\n";
                    cout << "1. Get List of Users and Account Details\n2. Logout\n";
                    cin >> bankingOption;
                    if (bankingOption == 1) {
                        ifstream userFile("users.txt");
                        if (userFile.is_open()) {
                            string line;
                            while (getline(userFile, line)) {
                                cout << line << endl;
                            }
                            userFile.close();
                        }
                    }
                    if (bankingOption == 2) {
                        managerLoggedIn = false;
                        loggedIn = false;
                    }
                }
            } else if (choice == 4) {
                break; // Exit the program
            }
        } else {
            if (managerLoggedIn) {
                cout << "Manager Options\n";
                cout << "1. Get List of Users and Account Details\n2. Logout\n";
                cin >> bankingOption;
                if (bankingOption == 1) {
                    ifstream userFile("users.txt");
                    if (userFile.is_open()) {
                        string line;
                        while (getline(userFile, line)) {
                            cout << line << endl;
                        }
                        userFile.close();
                    }
                }
                if (bankingOption == 2) {
                    loggedIn = false;
                }
            } else {
                // Account login options
                cout << "User Options:\n";
                cout << "1. Withdraw\n2. Deposit\n3. Get Account Summary\n4. Close Account\n5. Logout\n";
                cin >> bankingOption;
                if (bankingOption == 1) {
                    cout << "Please enter withdrawal amount: ";
                    cin >> withdrawAmt;
                    acc.Withdraw(withdrawAmt);
                } else if (bankingOption == 2) {
                    cout << "Please enter deposit amount: ";
                    cin >> depositAmt;
                    acc.Deposit(depositAmt);
                } else if (bankingOption == 3) {
                    acc.PrintAccountSummary();
                } else if (bankingOption == 4) {
                    acc.CloseAccount(database);
                    loggedIn = false;
                } else if (bankingOption == 5) {
                    loggedIn = false;
                }
            }
        }
    }
    return 0;
}

Jessica Janko

Jessica Janko is a third-year undergraduate at the University of Connecticut pursuing a Bachelor's in Computer Science with a curiosity in software development and cybersecurity.

Read More

Improved & Reviewed by:


Aditya Chatterjee Aditya Chatterjee
Bank Management System in C++ [Project with source code]
Share this