Menu
Coddy logo textTech

Банковская система

Часть раздела Объектно-ориентированное программирование путешествия по C++ на Coddy — урок 104 из 104.

challenge icon

Задание

Легко

Давайте создадим банковскую систему, которая демонстрирует паттерн Состояние (State), наследование и управление умными указателями. Вы создадите систему, в которой счета могут находиться в разных состояниях (Active, Frozen, Closed), каждое из которых имеет свои особенности обработки транзакций.

Вы организуете свой код в шести файлах:

  • AccountState.h: Определите инфраструктуру паттерна Состояние для состояний счета.

    Создайте абстрактный базовый класс AccountState с чисто виртуальными методами:

    • deposit(double amount) — возвращает true, если депозит разрешен, иначе false
    • withdraw(double amount) — возвращает true, если снятие разрешено, иначе false
    • getStateName() — возвращает название состояния в виде строки

    Реализуйте три конкретных состояния:

    • ActiveState: Разрешает как депозиты, так и снятие средств, возвращает "Active"
    • FrozenState: Разрешает депозиты, но отклоняет снятие средств, возвращает "Frozen"
    • ClosedState: Отклоняет как депозиты, так и снятие средств, возвращает "Closed"
  • Account.h: Постройте иерархию счетов с управлением состоянием.

    Создайте базовый класс Account с:

    • Номером счета (string), именем владельца и балансом
    • std::unique_ptr<AccountState> для управления текущим состоянием
    • deposit(double amount) — сначала проверяет состояние; если разрешено, добавляет к балансу и выводит "Deposited [amount] to [accountNumber]", иначе выводит "Deposit rejected: account is [stateName]"
    • withdraw(double amount) — проверяет состояние; если разрешено и средств достаточно, списывает и выводит "Withdrew [amount] from [accountNumber]". Если состояние отклоняет операцию, выводит "Withdrawal rejected: account is [stateName]". Если средств недостаточно, выводит "Insufficient funds"
    • freeze(), activate() и close() — изменяют состояние счета
    • getInfo() — возвращает "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • Виртуальный getAccountType(), возвращающий "Basic"

    Создайте два производных типа счетов:

    • SavingsAccount: Имеет требование к минимальному балансу (передается в конструктор). Переопределите withdraw, чтобы также проверять, не упадет ли баланс ниже минимума после снятия — если да, выведите "Cannot go below minimum balance of [minimum]". Возвращает "Savings" в качестве типа счета.
    • CheckingAccount: Имеет лимит овердрафта (передается в конструктор). Позволяет снимать средства в пределах (balance + overdraftLimit). Возвращает "Checking" в качестве типа счета.
  • Transaction.h: Моделируйте транзакции как объекты.

    Создайте класс Transaction, который записывает:

    • Тип транзакции (string: "Deposit", "Withdrawal", "Transfer")
    • Сумму
    • Номер задействованного счета
    • Статус успеха (bool)

    Добавьте метод getDescription(), возвращающий "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h: Создайте клиента, который владеет несколькими счетами.

    У Customer есть имя, ID и вектор std::shared_ptr<Account>. Реализуйте:

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber) — возвращает соответствующий счет или nullptr
    • getTotalBalance() — суммирует балансы всех счетов
    • listAccounts() — выводит информацию о каждом счете
  • Bank.h: Координируйте банковские операции.

    Класс Bank хранит клиентов и ведет историю транзакций. Реализуйте:

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber) — ищет счет среди всех клиентов
    • processDeposit(const std::string& accountNumber, double amount) — находит счет, выполняет депозит, записывает транзакцию
    • processWithdrawal(const std::string& accountNumber, double amount) — находит счет, выполняет снятие, записывает транзакцию
    • getTransactionCount() — возвращает общее количество обработанных транзакций
  • main.cpp: Продемонстрируйте вашу банковскую систему.

    Прочитайте четыре входных значения:

    1. Данные клиента (формат: name,customerId)
    2. Данные сберегательного счета (формат: accountNumber,minBalance)
    3. Операция 1 (формат: action,accountNumber,amount, где action — это deposit или withdraw)
    4. Операция 2 (формат: action,accountNumber,amount или freeze,accountNumber)

    Создайте банк и клиента. Создайте сберегательный счет с клиентом в качестве владельца и добавьте его клиенту. Добавьте клиента в банк. Обработайте обе операции (если это команда freeze, заморозьте счет, а затем попробуйте снять небольшую сумму в $10, чтобы продемонстрировать состояние). Наконец, выведите список счетов клиента и общее количество транзакций в формате "Transactions: [count]".

Например, при входных данных Alice,C001, SAV001,100, deposit,SAV001,500 и withdraw,SAV001,200:

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

При входных данных Bob,C002, SAV002,50, deposit,SAV002,100 и freeze,SAV002:

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

При входных данных Carol,C003, SAV003,200, deposit,SAV003,250 и withdraw,SAV003,100:

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

Эта задача объединяет паттерн Состояние для управления поведением счетов, наследование для различных типов счетов, умные указатели для отношений владения и отслеживание транзакций — все основные концепции, которые вы освоили в этом курсе.

Попробуйте сами

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

int main() {
    // Чтение входных данных 1: сведения о клиенте (формат: name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // Чтение входных данных 2: сведения о сберегательном счете (формат: accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // Чтение входных данных 3: Операция 1 (формат: action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // Чтение входных данных 4: Операция 2 (формат: action,accountNumber,amount или freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: Разобрать сведения о клиенте из customerInput
    // Подсказка: используйте find(',') для разделения строки
    
    // TODO: Разобрать сведения о счете из accountInput
    
    // TODO: Создать банк
    
    // TODO: Создать клиента
    
    // TODO: Создать сберегательный счет, владельцем которого является клиент
    
    // TODO: Добавить счет клиенту
    
    // TODO: Добавить клиента в банк
    
    // TODO: Разобрать и обработать операцию 1
    // Формат: action,accountNumber,amount (action — это "deposit" или "withdraw")
    
    // TODO: Разобрать и обработать операцию 2
    // Может быть: action,accountNumber,amount ИЛИ freeze,accountNumber
    // Если freeze, заморозить счет, а затем попытаться снять $10
    
    // TODO: Вывести список счетов клиента
    
    // TODO: Вывести количество транзакций в формате "Transactions: [count]"
    
    return 0;
}

Все уроки раздела Объектно-ориентированное программирование

15Финальные испытания

Платформа для онлайн-обученияБанковская система