Menu
Coddy logo textTech

Sistema bancario

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 104 di 104.

challenge icon

Sfida

Facile

Costruiamo un sistema bancario che dimostri il pattern State, l'ereditarietà e la gestione con puntatori intelligenti. Creerai un sistema in cui i conti possono trovarsi in stati diversi (Active, Frozen, Closed), ciascuno con comportamenti distinti per la gestione delle transazioni.

Organizzerai il codice in sei file:

  • AccountState.h: definisci l'infrastruttura del pattern State per gli stati dei conti.

    Crea una classe base astratta AccountState con metodi virtuali puri:

    • deposit(double amount): restituisce true se il deposito è consentito, false altrimenti
    • withdraw(double amount): restituisce true se il prelievo è consentito, false altrimenti
    • getStateName(): restituisce il nome dello stato come stringa

    Implementa tre stati concreti:

    • ActiveState: consente sia i depositi sia i prelievi, restituisce "Active"
    • FrozenState: consente i depositi ma rifiuta i prelievi, restituisce "Frozen"
    • ClosedState: rifiuta sia i depositi sia i prelievi, restituisce "Closed"
  • Account.h: crea una gerarchia di conti con gestione degli stati.

    Crea una classe base Account con:

    • Numero del conto (stringa), nome del titolare e saldo
    • Un std::unique_ptr<AccountState> per gestire lo stato corrente
    • deposit(double amount): verifica prima lo stato; se il deposito è consentito, aggiunge l'importo al saldo e stampa "Deposited [amount] to [accountNumber]", altrimenti stampa "Deposit rejected: account is [stateName]"
    • withdraw(double amount): verifica lo stato; se il prelievo è consentito e i fondi sono sufficienti, detrae l'importo e stampa "Withdrew [amount] from [accountNumber]". Se lo stato rifiuta il prelievo, stampa "Withdrawal rejected: account is [stateName]". Se i fondi sono insufficienti, stampa "Insufficient funds"
    • freeze(), activate() e close(): cambiano lo stato del conto
    • getInfo(): restituisce "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • getAccountType() virtuale che restituisce "Basic"

    Crea due tipi di conto derivati:

    • SavingsAccount: prevede un saldo minimo (passato al costruttore). Sovrascrivi withdraw per verificare anche se il prelievo farebbe scendere il saldo sotto il minimo; in tal caso, stampa "Cannot go below minimum balance of [minimum]". Restituisce "Savings" come tipo di conto.
    • CheckingAccount: prevede un limite di scoperto (passato al costruttore). Consente prelievi fino a (saldo + overdraftLimit). Restituisce "Checking" come tipo di conto.
  • Transaction.h: modella le transazioni come oggetti.

    Crea una classe Transaction che registri:

    • Tipo di transazione (stringa: "Deposit", "Withdrawal", "Transfer")
    • Importo
    • Numero del conto coinvolto
    • Esito (bool)

    Aggiungi un metodo getDescription() che restituisca "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h: crea un cliente che possiede più conti.

    Un Customer ha un nome, un ID e un vector di std::shared_ptr<Account>. Implementa:

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber): restituisce il conto corrispondente oppure nullptr
    • getTotalBalance(): somma i saldi di tutti i conti
    • listAccounts(): stampa le informazioni di ciascun conto
  • Bank.h: coordina le operazioni bancarie.

    La classe Bank memorizza i clienti e mantiene uno storico delle transazioni. Implementa:

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber): cerca il conto tra tutti i clienti
    • processDeposit(const std::string& accountNumber, double amount): trova il conto, effettua il deposito e registra la transazione
    • processWithdrawal(const std::string& accountNumber, double amount): trova il conto, effettua il prelievo e registra la transazione
    • getTransactionCount(): restituisce il totale delle transazioni elaborate
  • main.cpp: mostra il funzionamento del sistema bancario.

    Leggi quattro input:

    1. Dati del cliente (formato: name,customerId)
    2. Dati del conto di risparmio (formato: accountNumber,minBalance)
    3. Operazione 1 (formato: action,accountNumber,amount, dove action è deposit oppure withdraw)
    4. Operazione 2 (formato: action,accountNumber,amount oppure freeze,accountNumber)

    Crea la banca e il cliente. Crea un conto di risparmio intestato al cliente e aggiungilo al cliente. Aggiungi il cliente alla banca. Esegui entrambe le operazioni (se è un comando freeze, congela il conto e poi prova un piccolo prelievo di $10 per mostrare lo stato). Infine, stampa l'elenco dei conti del cliente e il numero totale di transazioni nel formato "Transactions: [count]".

Per esempio, con gli input Alice,C001, SAV001,100, deposit,SAV001,500 e withdraw,SAV001,200:

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

Con gli input Bob,C002, SAV002,50, deposit,SAV002,100 e freeze,SAV002:

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

Con gli input Carol,C003, SAV003,200, deposit,SAV003,250 e withdraw,SAV003,100:

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

Questa sfida riunisce il pattern State per gestire i comportamenti dei conti, l'ereditarietà per i diversi tipi di conto, i puntatori intelligenti per le relazioni di proprietà e il tracciamento delle transazioni: tutti concetti fondamentali che hai imparato durante questo corso.

Provalo tu

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

int main() {
    // Leggi l'input 1: dati del cliente (formato: name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // Leggi l'input 2: dati del conto di risparmio (formato: accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // Leggi l'input 3: operazione 1 (formato: action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // Leggi l'input 4: operazione 2 (formato: action,accountNumber,amount oppure freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: Estrai i dati del cliente da customerInput
    // Suggerimento: usa find(',') per suddividere la stringa
    
    // TODO: Estrai i dati del conto da accountInput
    
    // TODO: Crea la banca
    
    // TODO: Crea il cliente
    
    // TODO: Crea un conto di risparmio intestato al cliente
    
    // TODO: Aggiungi il conto al cliente
    
    // TODO: Aggiungi il cliente alla banca
    
    // TODO: Analizza ed esegui l'operazione 1
    // Formato: action,accountNumber,amount (action è "deposit" o "withdraw")
    
    // TODO: Analizza ed esegui l'operazione 2
    // Può essere: action,accountNumber,amount oppure freeze,accountNumber
    // Se l'azione è freeze, blocca il conto e poi prova a prelevare $10
    
    // TODO: Stampa l'elenco dei conti del cliente
    
    // TODO: Stampa il numero di transazioni nel formato "Transactions: [count]"
    
    return 0;
}

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online