Menu
Coddy logo textTech

Banking System

Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 104 of 104.

challenge icon

Challenge

Easy

Let's build a Banking System that demonstrates the State pattern, inheritance, and smart pointer management. You'll create a system where accounts can be in different states (Active, Frozen, Closed), each with distinct behaviors for handling transactions.

You'll organize your code across six files:

  • AccountState.h: Define the State pattern infrastructure for account states.

    Create an abstract AccountState base class with pure virtual methods:

    • deposit(double amount) — returns true if deposit is allowed, false otherwise
    • withdraw(double amount) — returns true if withdrawal is allowed, false otherwise
    • getStateName() — returns the state name as a string

    Implement three concrete states:

    • ActiveState: Allows both deposits and withdrawals, returns "Active"
    • FrozenState: Allows deposits but rejects withdrawals, returns "Frozen"
    • ClosedState: Rejects both deposits and withdrawals, returns "Closed"
  • Account.h: Build an account hierarchy with state management.

    Create a base Account class with:

    • Account number (string), owner name, and balance
    • A std::unique_ptr<AccountState> to manage the current state
    • deposit(double amount) — checks with state first, if allowed adds to balance and prints "Deposited [amount] to [accountNumber]", otherwise prints "Deposit rejected: account is [stateName]"
    • withdraw(double amount) — checks with state, if allowed and sufficient funds, deducts and prints "Withdrew [amount] from [accountNumber]". If state rejects, print "Withdrawal rejected: account is [stateName]". If insufficient funds, print "Insufficient funds"
    • freeze() and activate() and close() — change the account state
    • getInfo() — returns "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • Virtual getAccountType() returning "Basic"

    Create two derived account types:

    • SavingsAccount: Has a minimum balance requirement (passed to constructor). Override withdraw to also check if the withdrawal would drop below minimum — if so, print "Cannot go below minimum balance of [minimum]". Returns "Savings" for account type.
    • CheckingAccount: Has an overdraft limit (passed to constructor). Allows withdrawals up to (balance + overdraftLimit). Returns "Checking" for account type.
  • Transaction.h: Model transactions as objects.

    Create a Transaction class that records:

    • Transaction type (string: "Deposit", "Withdrawal", "Transfer")
    • Amount
    • Account number involved
    • Success status (bool)

    Add a getDescription() method returning "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h: Create a customer who owns multiple accounts.

    A Customer has a name, ID, and a vector of std::shared_ptr<Account>. Implement:

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber) — returns the matching account or nullptr
    • getTotalBalance() — sums balances across all accounts
    • listAccounts() — prints each account's info
  • Bank.h: Coordinate the banking operations.

    The Bank class stores customers and maintains a transaction history. Implement:

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber) — searches all customers for the account
    • processDeposit(const std::string& accountNumber, double amount) — finds account, performs deposit, records transaction
    • processWithdrawal(const std::string& accountNumber, double amount) — finds account, performs withdrawal, records transaction
    • getTransactionCount() — returns total transactions processed
  • main.cpp: Demonstrate your banking system.

    Read four inputs:

    1. Customer details (format: name,customerId)
    2. Savings account details (format: accountNumber,minBalance)
    3. Operation 1 (format: action,accountNumber,amount where action is deposit or withdraw)
    4. Operation 2 (format: action,accountNumber,amount or freeze,accountNumber)

    Create the bank and customer. Create a savings account with the customer as owner and add it to the customer. Add the customer to the bank. Process both operations (if it's a freeze command, freeze the account then try a small withdrawal of $10 to demonstrate the state). Finally, print the customer's account list and the total transaction count as "Transactions: [count]".

For example, with inputs Alice,C001, SAV001,100, deposit,SAV001,500, and withdraw,SAV001,200:

Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2

With inputs Bob,C002, SAV002,50, deposit,SAV002,100, and freeze,SAV002:

Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2

With inputs Carol,C003, SAV003,200, deposit,SAV003,250, and withdraw,SAV003,100:

Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2

This challenge brings together the State pattern for managing account behaviors, inheritance for different account types, smart pointers for ownership relationships, and transaction tracking — all core concepts you've mastered throughout this course.

Try it yourself

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"

int main() {
    // Read input 1: Customer details (format: name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // Read input 2: Savings account details (format: accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // Read input 3: Operation 1 (format: action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // Read input 4: Operation 2 (format: action,accountNumber,amount or freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: Parse customer details from customerInput
    // Hint: Use find(',') to split the string
    
    // TODO: Parse account details from accountInput
    
    // TODO: Create the bank
    
    // TODO: Create the customer
    
    // TODO: Create a savings account with the customer as owner
    
    // TODO: Add the account to the customer
    
    // TODO: Add the customer to the bank
    
    // TODO: Parse and process operation 1
    // Format: action,accountNumber,amount (action is "deposit" or "withdraw")
    
    // TODO: Parse and process operation 2
    // Could be: action,accountNumber,amount OR freeze,accountNumber
    // If freeze, freeze the account then try a withdrawal of $10
    
    // TODO: Print the customer's account list
    
    // TODO: Print transaction count as "Transactions: [count]"
    
    return 0;
}

All lessons in Object Oriented Programming