Menu
Coddy logo textTech

Sistema bancario

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 104 de 104.

challenge icon

Desafío

Fácil

Construyamos un sistema bancario que demuestre el patrón State, la herencia y la gestión de punteros inteligentes. Crearás un sistema en el que las cuentas pueden estar en distintos estados (Active, Frozen, Closed), cada uno con comportamientos diferentes para gestionar las transacciones.

Organizarás tu código en seis archivos:

  • AccountState.h: Define la infraestructura del patrón State para los estados de las cuentas.

    Crea una clase base abstracta AccountState con métodos virtuales puros:

    • deposit(double amount): devuelve true si se permite el depósito y false en caso contrario
    • withdraw(double amount): devuelve true si se permite el retiro y false en caso contrario
    • getStateName(): devuelve el nombre del estado como una cadena

    Implementa tres estados concretos:

    • ActiveState: permite tanto depósitos como retiros y devuelve "Active"
    • FrozenState: permite depósitos, pero rechaza retiros, y devuelve "Frozen"
    • ClosedState: rechaza tanto depósitos como retiros y devuelve "Closed"
  • Account.h: Construye una jerarquía de cuentas con gestión de estados.

    Crea una clase base Account con:

    • Número de cuenta (cadena), nombre del titular y saldo
    • Un std::unique_ptr<AccountState> para gestionar el estado actual
    • deposit(double amount): comprueba primero el estado; si se permite, suma el importe al saldo e imprime "Deposited [amount] to [accountNumber]"; de lo contrario, imprime "Deposit rejected: account is [stateName]"
    • withdraw(double amount): comprueba el estado; si se permite y hay fondos suficientes, descuenta el importe e imprime "Withdrew [amount] from [accountNumber]". Si el estado lo rechaza, imprime "Withdrawal rejected: account is [stateName]". Si no hay fondos suficientes, imprime "Insufficient funds"
    • freeze(), activate() y close(): cambian el estado de la cuenta
    • getInfo(): devuelve "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • getAccountType() virtual que devuelve "Basic"

    Crea dos tipos de cuenta derivados:

    • SavingsAccount: tiene un requisito de saldo mínimo (que se pasa al constructor). Sobrescribe withdraw para comprobar también si el retiro haría que el saldo quedara por debajo del mínimo; si es así, imprime "Cannot go below minimum balance of [minimum]". Devuelve "Savings" como tipo de cuenta.
    • CheckingAccount: tiene un límite de sobregiro (que se pasa al constructor). Permite retiros de hasta (saldo + overdraftLimit). Devuelve "Checking" como tipo de cuenta.
  • Transaction.h: Modela las transacciones como objetos.

    Crea una clase Transaction que registre:

    • Tipo de transacción (cadena: "Deposit", "Withdrawal", "Transfer")
    • Importe
    • Número de cuenta involucrado
    • Estado de éxito (bool)

    Añade un método getDescription() que devuelva "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h: Crea un cliente que sea propietario de varias cuentas.

    Un Customer tiene un nombre, un ID y un vector de std::shared_ptr<Account>. Implementa:

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber): devuelve la cuenta coincidente o nullptr
    • getTotalBalance(): suma los saldos de todas las cuentas
    • listAccounts(): imprime la información de cada cuenta
  • Bank.h: Coordina las operaciones bancarias.

    La clase Bank almacena clientes y mantiene un historial de transacciones. Implementa:

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber): busca la cuenta entre todos los clientes
    • processDeposit(const std::string& accountNumber, double amount): encuentra la cuenta, realiza el depósito y registra la transacción
    • processWithdrawal(const std::string& accountNumber, double amount): encuentra la cuenta, realiza el retiro y registra la transacción
    • getTransactionCount(): devuelve el total de transacciones procesadas
  • main.cpp: Demuestra tu sistema bancario.

    Lee cuatro entradas:

    1. Datos del cliente (formato: name,customerId)
    2. Datos de la cuenta de ahorros (formato: accountNumber,minBalance)
    3. Operación 1 (formato: action,accountNumber,amount, donde action es deposit o withdraw)
    4. Operación 2 (formato: action,accountNumber,amount o freeze,accountNumber)

    Crea el banco y el cliente. Crea una cuenta de ahorros cuyo titular sea el cliente y añádela al cliente. Añade el cliente al banco. Procesa ambas operaciones (si es un comando freeze, congela la cuenta y luego intenta realizar un pequeño retiro de $10 para demostrar el estado). Finalmente, imprime la lista de cuentas del cliente y el número total de transacciones como "Transactions: [count]".

Por ejemplo, con las entradas Alice,C001, SAV001,100, deposit,SAV001,500 y withdraw,SAV001,200:

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

Con las entradas Bob,C002, SAV002,50, deposit,SAV002,100 y freeze,SAV002:

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

Con las entradas Carol,C003, SAV003,200, deposit,SAV003,250 y withdraw,SAV003,100:

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

Este desafío reúne el patrón State para gestionar los comportamientos de las cuentas, la herencia para los distintos tipos de cuenta, los punteros inteligentes para las relaciones de propiedad y el seguimiento de transacciones: todos son conceptos fundamentales que has dominado a lo largo de este curso.

Pruébalo tú mismo

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

int main() {
    // Leer entrada 1: Detalles del cliente (formato: name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // Leer entrada 2: Detalles de la cuenta de ahorros (formato: accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // Leer entrada 3: Operación 1 (formato: action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // Leer entrada 4: Operación 2 (formato: action,accountNumber,amount o freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: Analiza los detalles del cliente desde customerInput
    // Pista: Usa find(',') para dividir la cadena
    
    // TODO: Analiza los detalles de la cuenta desde accountInput
    
    // TODO: Crea el banco
    
    // TODO: Crea el cliente
    
    // TODO: Crea una cuenta de ahorros con el cliente como propietario
    
    // TODO: Añade la cuenta al cliente
    
    // TODO: Añade el cliente al banco
    
    // TODO: Analiza y procesa la operación 1
    // Formato: action,accountNumber,amount (action es "deposit" o "withdraw")
    
    // TODO: Analiza y procesa la operación 2
    // Podría ser: action,accountNumber,amount O freeze,accountNumber
    // Si freeze, congela la cuenta y luego intenta un retiro de $10
    
    // TODO: Imprime la lista de cuentas del cliente
    
    // TODO: Print transaction count as "Transactions: [count]"
    
    return 0;
}

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online