Menu
Coddy logo textTech

System bankowy

Część sekcji Programowanie obiektowe ścieżki C++ w Coddy. Lekcja 104 z 104.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system bankowy, który demonstruje wzorzec State, dziedziczenie i zarządzanie inteligentnymi wskaźnikami. Stworzysz system, w którym konta mogą znajdować się w różnych stanach (Active, Frozen, Closed), z których każdy ma inne zachowanie podczas obsługi transakcji.

Rozmieścisz swój kod w sześciu plikach:

  • AccountState.h: Zdefiniuj infrastrukturę wzorca State dla stanów konta.

    Utwórz abstrakcyjną klasę bazową AccountState z czysto wirtualnymi metodami:

    • deposit(double amount): zwraca true, jeśli wpłata jest dozwolona, w przeciwnym razie false
    • withdraw(double amount): zwraca true, jeśli wypłata jest dozwolona, w przeciwnym razie false
    • getStateName(): zwraca nazwę stanu jako ciąg znaków

    Zaimplementuj trzy konkretne stany:

    • ActiveState: Zezwala na wpłaty i wypłaty, zwraca "Active"
    • FrozenState: Zezwala na wpłaty, ale odrzuca wypłaty, zwraca "Frozen"
    • ClosedState: Odrzuca wpłaty i wypłaty, zwraca "Closed"
  • Account.h: Zbuduj hierarchię kont z zarządzaniem stanem.

    Utwórz bazową klasę Account zawierającą:

    • Numer konta (ciąg znaków), imię i nazwisko właściciela oraz saldo
    • std::unique_ptr<AccountState> do zarządzania bieżącym stanem
    • deposit(double amount): najpierw sprawdza stan; jeśli wpłata jest dozwolona, dodaje kwotę do salda i wypisuje "Deposited [amount] to [accountNumber]", w przeciwnym razie wypisuje "Deposit rejected: account is [stateName]"
    • withdraw(double amount): sprawdza stan; jeśli wypłata jest dozwolona i są wystarczające środki, odejmuje kwotę i wypisuje "Withdrew [amount] from [accountNumber]". Jeśli stan odrzuca wypłatę, wypisuje "Withdrawal rejected: account is [stateName]". Jeśli brakuje środków, wypisuje "Insufficient funds"
    • freeze(), activate() i close(): zmieniają stan konta
    • getInfo(): zwraca "[accountNumber] ([ownerName]): $[balance] - [stateName]"
    • Wirtualna metoda getAccountType() zwracająca "Basic"

    Utwórz dwa typy kont pochodne:

    • SavingsAccount: Ma wymagane minimalne saldo (przekazywane do konstruktora). Nadpisz metodę withdraw, aby dodatkowo sprawdzała, czy wypłata obniży saldo poniżej minimum; jeśli tak, wypisz "Cannot go below minimum balance of [minimum]". Zwraca "Savings" jako typ konta.
    • CheckingAccount: Ma limit debetu (przekazywany do konstruktora). Zezwala na wypłaty do wysokości (salda + overdraftLimit). Zwraca "Checking" jako typ konta.
  • Transaction.h: Modeluj transakcje jako obiekty.

    Utwórz klasę Transaction, która zapisuje:

    • Typ transakcji (ciąg znaków: "Deposit", "Withdrawal", "Transfer")
    • Kwotę
    • Numer konta, którego dotyczy transakcja
    • Status powodzenia (bool)

    Dodaj metodę getDescription(), która zwraca "[type]: $[amount] on [accountNumber] - [Success/Failed]"

  • Customer.h: Utwórz klienta, który posiada wiele kont.

    Customer ma imię i nazwisko, ID oraz wektor elementów std::shared_ptr<Account>. Zaimplementuj:

    • addAccount(std::shared_ptr<Account> account)
    • getAccount(const std::string& accountNumber): zwraca pasujące konto lub nullptr
    • getTotalBalance(): sumuje salda wszystkich kont
    • listAccounts(): wypisuje informacje o każdym koncie
  • Bank.h: Koordynuj operacje bankowe.

    Klasa Bank przechowuje klientów i prowadzi historię transakcji. Zaimplementuj:

    • addCustomer(std::shared_ptr<Customer> customer)
    • findAccount(const std::string& accountNumber): wyszukuje konto u wszystkich klientów
    • processDeposit(const std::string& accountNumber, double amount): znajduje konto, wykonuje wpłatę i zapisuje transakcję
    • processWithdrawal(const std::string& accountNumber, double amount): znajduje konto, wykonuje wypłatę i zapisuje transakcję
    • getTransactionCount(): zwraca łączną liczbę przetworzonych transakcji
  • main.cpp: Zademonstruj działanie systemu bankowego.

    Wczytaj cztery dane wejściowe:

    1. Dane klienta (format: name,customerId)
    2. Dane konta oszczędnościowego (format: accountNumber,minBalance)
    3. Operacja 1 (format: action,accountNumber,amount, gdzie action to deposit lub withdraw)
    4. Operacja 2 (format: action,accountNumber,amount lub freeze,accountNumber)

    Utwórz bank i klienta. Utwórz konto oszczędnościowe, którego właścicielem będzie klient, i dodaj je do klienta. Dodaj klienta do banku. Wykonaj obie operacje (jeśli jest to polecenie freeze, zamroź konto, a następnie spróbuj dokonać niewielkiej wypłaty w wysokości $10, aby zademonstrować działanie stanu). Na koniec wypisz listę kont klienta i łączną liczbę transakcji w formacie "Transactions: [count]".

Na przykład dla danych wejściowych Alice,C001, SAV001,100, deposit,SAV001,500 i withdraw,SAV001,200:

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

Dla danych wejściowych Bob,C002, SAV002,50, deposit,SAV002,100 i freeze,SAV002:

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

Dla danych wejściowych Carol,C003, SAV003,200, deposit,SAV003,250 i withdraw,SAV003,100:

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

To wyzwanie łączy wzorzec State do zarządzania zachowaniem kont, dziedziczenie dla różnych typów kont, inteligentne wskaźniki do relacji własności oraz śledzenie transakcji — wszystkie kluczowe koncepcje, które opanowałeś w trakcie tego kursu.

Spróbuj swoich sił

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

int main() {
    // Odczytaj dane wejściowe 1: dane klienta (format: name,customerId)
    std::string customerInput;
    std::getline(std::cin, customerInput);
    
    // Odczytaj dane wejściowe 2: dane konta oszczędnościowego (format: accountNumber,minBalance)
    std::string accountInput;
    std::getline(std::cin, accountInput);
    
    // Odczytaj dane wejściowe 3: operacja 1 (format: action,accountNumber,amount)
    std::string op1Input;
    std::getline(std::cin, op1Input);
    
    // Odczytaj dane wejściowe 4: operacja 2 (format: action,accountNumber,amount lub freeze,accountNumber)
    std::string op2Input;
    std::getline(std::cin, op2Input);
    
    // TODO: Odczytaj dane klienta z customerInput
    // Wskazówka: użyj find(',') do podzielenia ciągu znaków
    
    // TODO: Odczytaj dane konta z accountInput
    
    // TODO: Utwórz bank
    
    // TODO: Utwórz klienta
    
    // TODO: Utwórz konto oszczędnościowe, którego właścicielem jest klient
    
    // TODO: Dodaj konto do klienta
    
    // TODO: Dodaj klienta do banku
    
    // TODO: Przeanalizuj i przetwórz operację 1
    // Format: action,accountNumber,amount (action to "deposit" lub "withdraw")
    
    // TODO: Przeanalizuj i przetwórz operację 2
    // Możliwe formaty: action,accountNumber,amount lub freeze,accountNumber
    // Jeśli podano freeze, zablokuj konto, a następnie spróbuj wypłacić $10
    
    // TODO: Wyświetl listę kont klienta
    
    // TODO: Wyświetl liczbę transakcji w postaci "Transactions: [count]"
    
    return 0;
}

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator C++ online