Personal Bank Account Management Procedure

This program is a bank account management program, which uses C++ to implement the program functions. The program contains six files, including date.h header file

Is the header file for the date class, date.cpp is the implementation file for the date class, and accumulator.h is the header file for the accumulator class that adds values by day.

account.h is the header file for each savings account class definition, account.cpp is the implementation file for each savings account class, and the main function file.this

The program includes the functions of increasing account, depositing, withdrawing, querying account information, changing date, and processing into the next month.

Then exit the program.Here are the individual program files:

Header file for 1.date.h date class

#ifndef _DATE_H
#define _DATE_H
#include <iostream>
using namespace std;
class Date
{
public:
    Date(int year = 1,int month = 1,int day = 1);
    int getYear()const
    {
        return year;
    }
    int getMonth()const
    {
        return month;
    }
    int getDay()const
    {
        return day;
    }
    int getMaxDay()const;        //Get the number of days in the month
    bool isLeapYear() const      //Determine if the year is leap
    {
        return year % 4 == 0 && year % 100 != 0 && year % 400 == 0;
    }
    void show()const;        //Output current date
    int operator-(const Date &date)const      //Calculate the difference between two dates
    {
        return totalDays - date.totalDays;
    }
    bool operator<(const Date &date)const     //Determine the order of two dates
    {
        return totalDays < date.totalDays;
    }
private:
    int year;
    int month;
    int day;
    int totalDays;       //The date begins on January 1, A.D.
};
istream& operator >> (istream &in, Date &date);
ostream& operator << (ostream &out, const Date &date);

#endif

2.date.cpp date class implementation file

#include <iostream>
#include <stdexcept>
#include "date.h"
using namespace std;

namespace      //namespace Make the following definitions valid only in the current file
{
    //For convenience, store the number of days before the first day of a month in the year getMaxDay The implementation of the function, which has one more item in the array
    const int DAYS_BEFORE_MONTH[] = { 0,31,59,90,120,151,181,212,243,273,304,334,365 };
}
Date::Date(int year, int month, int day):year(year),month(month),day(day)
{
    if (day <= 0 || day > getMaxDay())throw runtime_error("Invalid date");
    int years = year - 1;
    totalDays = years * 365 + years / 4 - years / 100 + years / 400 + DAYS_BEFORE_MONTH[month - 1] + day;
    if (isLeapYear() && month > 2)
        totalDays++;
}
int Date::getMaxDay()const
{
    if (isLeapYear() && month == 2)
        return 29;
    else
        return DAYS_BEFORE_MONTH[month] - DAYS_BEFORE_MONTH[month - 1];
}
void Date::show()const
{
    cout << getYear() << "-" << getMonth() << "-" << getDay();
}
istream& operator >> (istream &in, Date &date)
{
    int year, month, day;
    char c1, c2;
    in >> year >> c1 >> month >> c2 >> day;
    if (c1 != '-' || c2 != '-')
        throw runtime_error("Bad time format");
    date = Date(year, month, day);
    return in;
}
ostream& operator<<(ostream &out, const Date &date)
{
    out << date.getYear() << "-" << date.getMonth() << "-" << date.getDay();
    return out;
}

3.accumulator.h Header file that adds values by day

#ifndef _ACCUMULATOR_H
#define _ACCUMULATOR_H
#include "date.h"
class Accumulator            //Accumulate a value by day
{
public:
    //date For the date on which the accumulation begins, value Is Initial
    Accumulator(const Date &date, double value):lastDate(date),value(value),sum(0)
    {
    }
    double getSum(const Date &date)const
    {
        return sum + value*(date - lastDate);
    }
    //stay date Change Value to value
    void change(const Date &date, double value)
    {
        sum = getSum(date);
        lastDate = date;
        this->value = value;
    }
    //Initialize, change date to date,Value becomes value,Accumulator Zeroing
    void reset(const Date &date, double value)
    {
        lastDate = date;
        this->value = value;
        sum = 0;
    }
private:
    Date lastDate;           //Time when the value was last changed
    double value;            //Current value of value
    double sum;              //Sum of values by day
};

#endif

4.account.h Header file for each savings account class definition

#ifndef _ACCOUNT_H
#define _ACCOUNT_H
#include "date.h"
#include "accumulator.h"
#include <iostream>
#include <string>
#include <map>
#include <istream>
#include <stdexcept>
using namespace std;

class Account;
class AccountRecord        //Account records
{
public:
    AccountRecord(const Date &date, const Account* account, double amount, double balance, const string &desc);
    void show()const;          //Output Current Record
private:
    Date date;                 //date
    const Account* account;    //account
    double amount;             //Amount of money
    double balance;            //balance
    string desc;               //describe
};

typedef multimap<Date, AccountRecord> RecordMap;
//Account Class
class Account
{
public:
    const string& getId()const
    {
        return id;
    }
    double getBalance()const
    {
        return balance;
    }
    static double getTotal()
    {
        return total;
    }
    //Cash deposited, date Is the date, amount For money, desc Description of payments
    virtual void deposit(const Date &date, double amount, const string &desc) = 0;
    //Gold is withdrawn. date Is the date, amount For money, desc Description of payments
    virtual void withdraw(const Date &date, double amount, const string &desc) = 0;
    //Settlement, once a month, date For settlement date
    virtual void settle(const Date &date) = 0;
    //Show account information
    virtual void show(ostream &out)const;
    //Query account records for a specified time
    static void query(const Date &begin, const Date &end);
protected:
    //Constructor for Derived Class Call
    Account(const Date &date, const string &id);
    //Record an account, date Is the date, amount For money, desc For illustration
    void record(const Date &date, double amount, const string &desc);
    //Report Error Information
    void error(const string &msg)const;
private:
    string id;              //account
    double balance;         //balance
    static double total;    //Total amount of all accounts
    static RecordMap recordMap;    //Account records
};
inline ostream& operator<<(ostream &out, const Account &account)
{
    account.show(out);
    return out;
}

class SavingAccount :public Account         //Savings account class
{
public:
    SavingAccount(const Date &date, const string &id, double rate);
    double getRate()const
    {
        return rate;
    }
    //Cash deposits
    void deposit(const Date &date, double amount, const string &desc);
    //Withdrawal of cash
    void withdraw(const Date &date, double amount, const string &desc);
    //Settles interest, which is called once a year on January 1
    void settle(const Date &date);      
private:
    Accumulator acc;           //Accumulator to assist in calculating interest
    double rate;               //Annual interest rate on deposits
};

class CreditAccount :public Account        //Credit Account Class
{
public:
    CreditAccount(const Date &date, const string &id, double credit, double rate, double fee);
    double getCredit()const
    {
        return credit;
    }
    double getRate()const
    {
        return rate;
    }
    double getFee()const
    {
        return fee;
    }
    double getAvailableCredit()const            //Get available credit limit
    {
        if (getBalance() < 0)
            return credit + getBalance();
        else
            return credit;
    }
    //Cash deposits
    void deposit(const Date &date, double amount, const string &desc);
    //Withdrawal of cash
    void withdraw(const Date &date, double amount, const string &desc);
    //Settles interest and annual fees and calls this function once a month on the first day of the month
    void settle(const Date &date);
    virtual void show(ostream &out)const;
private:
    Accumulator acc;         //Accumulator to assist in calculating interest
    double credit;           //Credit limit
    double rate;             //Daily interest rate on arrears
    double fee;              //Annual Fee
    double getDebt() const   //Acquire arrears
    {
        double balance = getBalance();
        return (balance < 0 ? balance : 0);
    }
};

class AccountException :public runtime_error
{
public:
    AccountException(const Account* account, const string &msg) :runtime_error(msg), account(account)
    {
    }
    const Account* getAccount()const
    {
        return account;
    }
private:
    const Account* account;
};

#endif

5. Implementation files for each savings account class of account.cpp

#include <iostream>
#include <cmath>
#include <utility>
#include "account.h"
using namespace std;
using namespace std::rel_ops;

//AccountRecord Class implementation
AccountRecord::AccountRecord(const Date &date,const Account* account,double amount,double balance,const string &desc):\
date(date), account(account), amount(amount), balance(balance), desc(desc)
{
}
void AccountRecord::show()const
{
    cout << date << "\t#" << account->getId() << "\t" << amount << "\t" << balance << "\t" << desc << endl;
}

//Account Class implementation
double Account::total = 0;
RecordMap Account::recordMap;
Account::Account(const Date &date, const string &id):id(id),balance(0)
{
    cout << date << "\t#" << id << " created" << endl;
}
void Account::record(const Date &date, double amount, const string &desc)
{
    amount = floor(amount * 100 + 0.5) / 100;      //Keep the last two decimal places
    balance += amount;
    total += amount;
    date.show();
    cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl;
}
void Account::show(ostream &out)const
{
    out << id << "\tBalance: " << balance;
}
void Account::error(const string &msg)const
{
    throw AccountException(this, msg);
}
void Account::query(const Date &begin, const Date &end)
{
    if (begin <= end)
    {
        RecordMap::iterator iter1 = recordMap.lower_bound(begin);
        RecordMap::iterator iter2 = recordMap.upper_bound(end);
        for (RecordMap::iterator iter = iter1;iter != iter2;++iter)
            iter->second.show();
    }
}

//CreditAccount Class implementation
CreditAccount::CreditAccount(const Date &date,const string &id,double credit,double rate,double fee):\
Account(date, id), credit(credit), rate(rate), fee(fee), acc(date, 0)
{
}
void CreditAccount::deposit(const Date &date, double amount, const string &desc)
{
    record(date, amount, desc);
    acc.change(date, getDebt());
}
void CreditAccount::withdraw(const Date &date, double amount, const string &desc)
{
    if (amount - getBalance() > credit)
    {
        error("not enough credit");
    }
    else
    {
        record(date, -amount, desc);
        acc.change(date, getDebt());
    }
}
void CreditAccount::settle(const Date &date)
{
    double interest = acc.getSum(date)*rate;
    if (interest != 0)
        record(date, interest, "interest");
    if (date.getMonth() == 1)
        record(date, -fee, "annual fee");
    acc.reset(date, getDebt());
}
void CreditAccount::show(ostream &out)const
{
    Account::show(out);
    out << "\tAvailable credit: " << getAvailableCredit();
}

//SavingAccount Class implementation
SavingAccount::SavingAccount(const Date &date, const string &id, double rate) :Account(date, id), rate(rate), acc(date, 0)
{
}
void SavingAccount::deposit(const Date &date, double amount, const string &desc)
{
    record(date, amount, desc);
    acc.change(date, getBalance());
}
void SavingAccount::withdraw(const Date &date, double amount, const string &desc)
{
    if (amount > getBalance())
    {
        error("not enough money");
    }
    else
    {
        record(date, -amount, desc);
        acc.change(date, getBalance());
    }
}
void SavingAccount::settle(const Date &date)
{
    if (date.getMonth() == 1)        //Interest is calculated once a year in January
    {
        double interest = acc.getSum(date)*rate / (date - Date(date.getYear() - 1, 1, 1));
        if (interest != 0)
            record(date, interest, "interest");
        acc.reset(date, getBalance());
    }
}

6. Main Function File

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>
#include "account.h"
using namespace std;

struct deleter
{
    template<class T>void operator()(T *p)
    {
        delete p;
    }
};
//Controller class for storing account lists and processing commands
class Controller
{
public:
    Controller(const Date &date) :date(date), end(false)
    {
    }
    ~Controller();
    const Date& getDate()const
    {
        return date;
    }
    bool isEnd()const
    {
        return end;
    }
    //Execute a command to return whether it changed the current state(Is it necessary to save the current command)
    bool runCommand(const string &cmdLine);
private:
    Date date;
    vector<Account*> accounts;       //Account List
    bool end;                        //Whether the user entered an exit command
};
Controller::~Controller()
{
    for_each(accounts.begin(), accounts.end(), deleter());
}
bool Controller::runCommand(const string &cmdLine)
{
    istringstream str(cmdLine);
    char cmd, type;
    int index, day;
    double amount, credit, rate, fee;
    string id, desc;
    Account* account;
    Date date1, date2;
    str >> cmd;
    switch (cmd)
    {
    case 'a':               //Add Account
        str >> type >> id;
        if (type == 's')
        {
            str >> rate;
            account = new SavingAccount(date, id, rate);
        }
        else
        {
            str >> credit >> rate >> fee;
            account = new CreditAccount(date, id, credit, rate, fee);
        }
        accounts.push_back(account);
        return true;
    case 'd':              //Cash deposits
        str >> index >> amount;
        getline(str, desc);
        accounts[index]->deposit(date, amount, desc);
        return true;
    case 'w':              //Withdrawal of cash
        str >> index >> amount;
        getline(str, desc);
        accounts[index]->withdraw(date, amount, desc);
        return true;
    case 's':              //Query account information
        for (size_t i = 0;i < accounts.size();++i)
        {
            cout << "[" << i << "]";
            accounts[i]->show(cout);
            cout << endl;
        }
        return false;
    case 'c':             //Change Date
        str >> day;
        if (day < date.getDay())
            cout << "You cannot specify a previous day";
        else if (day > date.getMaxDay())
            cout << "Invalid day";
        else
            date = Date(date.getYear(), date.getMonth(), day);
        return true;
    case 'n':               //Enter next month
        if (date.getMonth() == 12)
            date = Date(date.getYear() + 1, 1, 1);
        else
            date = Date(date.getYear(), date.getMonth() + 1, 1);
        for (vector<Account*>::iterator iter = accounts.begin();iter != accounts.end();++iter)
            (*iter)->settle(date);
        return true;
    case 'q':             //Inquire into accounts over time
        str >> date1 >> date2;
        Account::query(date1, date2);
        return false;
    case 'e':             //Sign out
        end = true;
        return false;
    }
    cout << "Invalid command: " << cmdLine << endl;
    return false;
}
int main()
{
    Date date(2018, 1, 1);         //Start date
    Controller controller(date);
    string cmdLine;
    const char *FILE_NAME = "commands.txt";
    ifstream fileIn(FILE_NAME);      //Open file in read mode
    if (fileIn)                //If opened properly, execute every command in the file
    {
        while (getline(fileIn, cmdLine))
            controller.runCommand(cmdLine);
        fileIn.close();
    }
    ofstream fileOut(FILE_NAME, ios_base::app);        //Open file in append mode
    cout << "(a)add account  (d)deposit  (w)withdraw  (s)show  (c)change day  (n)next month  (q)query  (e)exit" << endl;
    while (!controller.isEnd())        //Read commands from standard input and execute them until you exit
    {
        cout << controller.getDate() << "\tTotal: " << Account::getTotal() << "\tcommand";
        string cmdLine;
        getline(cin, cmdLine);
        if (controller.runCommand(cmdLine))
            fileOut << cmdLine << endl;          //Write command to file
    }
    return 0;
}

Finally, run the main function to realize the program function, which can add account function, deposit function, withdrawal function, query account information function, change date work

Processing capabilities into the next month will allow the program to operate, with a final screenshot of how I operate these functions.

       

Tags: C++

Posted on Thu, 12 Mar 2020 12:41:44 -0400 by cachemony