Menu
Coddy logo textTech

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

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

challenge icon

Задание

Легко

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

Вы распределите код по шести файлам:

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

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

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

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

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

    Создайте базовый класс Account со следующими элементами:

    • Номер счета (строка), имя владельца и баланс
    • 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: имеет лимит овердрафта (передается конструктору). Разрешает снятие средств в пределах значения (баланс + overdraftLimit). Для типа счета возвращает "Checking".
  • Transaction.h: представьте транзакции в виде объектов.

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

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

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

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

    У Customer есть имя, идентификатор и вектор из 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

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

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

#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: Print transaction count as "Transactions: [count]"
    
    return 0;
}

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

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

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

Потренируйтесь самостоятельно: Онлайн-компилятор C++