Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نظام مصرفي

جزء من قسم البرمجة كائنية التوجه في رحلة 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: Allows both deposits and withdrawals, returns "Active"
    • FrozenState: Allows deposits but rejects withdrawals, returns "Frozen"
    • ClosedState: Rejects both deposits and withdrawals, returns "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;
}

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم C++ عبر الإنترنت