Menu
Coddy logo textTech

Système bancaire

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy — leçon 104 sur 104.

challenge icon

Défi

Facile

Construisons un système bancaire qui illustre le patron de conception State (État), l'héritage et la gestion des pointeurs intelligents. Vous allez créer un système où les comptes peuvent être dans différents états (Active, Frozen, Closed), chacun ayant des comportements distincts pour la gestion des transactions.

Vous organiserez votre code sur six fichiers :

  • AccountState.h : Définissez l'infrastructure du patron State pour les états de compte.

    Créez une classe de base abstraite AccountState avec des méthodes virtuelles pures :

    • deposit(double amount) — retourne true si le dépôt est autorisé, false sinon
    • withdraw(double amount) — retourne true si le retrait est autorisé, false sinon
    • getStateName() — retourne le nom de l'état sous forme de chaîne de caractères

    Implémentez trois états concrets :

    • ActiveState : Autorise à la fois les dépôts et les retraits, retourne "Active"
    • FrozenState : Autorise les dépôts mais rejette les retraits, retourne "Frozen"
    • ClosedState : Rejette à la fois les dépôts et les retraits, retourne "Closed"
  • Account.h : Construisez une hiérarchie de comptes avec gestion d'état.

    Créez une classe de base Account avec :

    • Un numéro de compte (chaîne), un nom de propriétaire et un solde
    • Un std::unique_ptr<AccountState> pour gérer l'état actuel
    • deposit(double amount) — vérifie d'abord l'état, si autorisé ajoute au solde et affiche "Deposited [amount] to [accountNumber]", sinon affiche "Deposit rejected: account is [stateName]"
    • withdraw(double amount) — vérifie l'état, si autorisé et fonds suffisants, déduit et affiche "Withdrew [amount] from [accountNumber]". Si l'état rejette, affiche "Withdrawal rejected: account is [stateName]". Si les fonds sont insuffisants, affiche "Insufficient funds"
    • freeze(), activate() et close() — changent l'état du compte
    • getInfo() — retourne "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • Une méthode virtuelle getAccountType() retournant "Basic"

    Créez deux types de comptes dérivés :

    • SavingsAccount : A une exigence de solde minimum (passée au constructeur). Surchargez withdraw pour vérifier également si le retrait ferait descendre le solde en dessous du minimum — si c'est le cas, affichez "Cannot go below minimum balance of [minimum]". Retourne "Savings" pour le type de compte.
    • CheckingAccount : A une limite de découvert (passée au constructeur). Autorise les retraits jusqu'à (balance + overdraftLimit). Retourne "Checking" pour le type de compte.
  • Transaction.h : Modélisez les transactions comme des objets.

    Créez une classe Transaction qui enregistre :

    • Le type de transaction (chaîne : "Deposit", "Withdrawal", "Transfer")
    • Le montant
    • Le numéro de compte concerné
    • Le statut de réussite (bool)

    Ajoutez une méthode getDescription() retournant "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h : Créez un client qui possède plusieurs comptes.

    Un Customer a un nom, un identifiant et un vecteur de std::shared_ptr<Account>. Implémentez :

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber) — retourne le compte correspondant ou nullptr
    • getTotalBalance() — additionne les soldes de tous les comptes
    • listAccounts() — affiche les informations de chaque compte
  • Bank.h : Coordonnez les opérations bancaires.

    La classe Bank stocke les clients et maintient un historique des transactions. Implémentez :

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber) — recherche le compte parmi tous les clients
    • processDeposit(const std::string& accountNumber, double amount) — trouve le compte, effectue le dépôt, enregistre la transaction
    • processWithdrawal(const std::string& accountNumber, double amount) — trouve le compte, effectue le retrait, enregistre la transaction
    • getTransactionCount() — retourne le nombre total de transactions traitées
  • main.cpp : Démontrez votre système bancaire.

    Lisez quatre entrées :

    1. Détails du client (format : name,customerId)
    2. Détails du compte d'épargne (format : accountNumber,minBalance)
    3. Opération 1 (format : action,accountNumber,amount où action est deposit ou withdraw)
    4. Opération 2 (format : action,accountNumber,amount ou freeze,accountNumber)

    Créez la banque et le client. Créez un compte d'épargne avec le client comme propriétaire et ajoutez-le au client. Ajoutez le client à la banque. Traitez les deux opérations (s'il s'agit d'une commande freeze, gelez le compte puis tentez un petit retrait de $10 pour démontrer l'état). Enfin, affichez la liste des comptes du client et le nombre total de transactions sous la forme "Transactions: [count]".

Par exemple, avec les entrées Alice,C001, SAV001,100, deposit,SAV001,500, et withdraw,SAV001,200 :

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

Avec les entrées Bob,C002, SAV002,50, deposit,SAV002,100, et freeze,SAV002 :

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

Avec les entrées Carol,C003, SAV003,200, deposit,SAV003,250, et withdraw,SAV003,100 :

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

Ce défi réunit le patron State pour la gestion des comportements de compte, l'héritage pour les différents types de comptes, les pointeurs intelligents pour les relations de propriété et le suivi des transactions — tous des concepts fondamentaux que vous avez maîtrisés tout au long de ce cours.

Essayez vous-même

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

int main() {
    // Lire l'entrée 1 : Détails du client (format : name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // Lire l'entrée 2 : Détails du compte d'épargne (format : accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // Lire l'entrée 3 : Opération 1 (format : action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // Lire l'entrée 4 : Opération 2 (format : action,accountNumber,amount ou freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: Analyser les détails du client à partir de customerInput
    // Astuce : Utilisez find(',') pour diviser la chaîne
    
    // TODO: Analyser les détails du compte à partir de accountInput
    
    // TODO: Créer la banque
    
    // TODO: Créer le client
    
    // TODO: Créer un compte d'épargne avec le client comme propriétaire
    
    // TODO: Ajouter le compte au client
    
    // TODO: Ajouter le client à la banque
    
    // TODO: Analyser et traiter l'opération 1
    // Format : action,accountNumber,amount (l'action est "deposit" ou "withdraw")
    
    // TODO: Analyser et traiter l'opération 2
    // Peut être : action,accountNumber,amount OU freeze,accountNumber
    // Si freeze, geler le compte puis tenter un retrait de $10
    
    // TODO: Afficher la liste des comptes du client
    
    // TODO: Afficher le nombre de transactions sous la forme "Transactions: [count]"
    
    return 0;
}

Toutes les leçons de Programmation Orientée Objet