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: הדפס את מספר העסקאות בפורמט "Transactions: [count]"
    
    return 0;
}

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C++ אונליין