#include #include #include #include //#include using namespace std; /* * Time struct * uses unix time which is seconds since 1/1/1970. */ struct Time { time_t time; // Seconds since EPOCH }; /* * Transaction struct * keeps the data for a single action on BankAccount. */ struct Transaction { string src_account; // Account number char type; // D=deposit, W=withdrawl, I=interest double amount; Time date; // Defaults to time(NULL)=now string dst_account; }; /* * BankAccount class * keeps the data for a BankAccount along with all of the * functions that apply to a BankAccount. */ class BankAccount { public: // Constructors BankAccount(); BankAccount(double balance, double rate); // Accessors/Mutators (setters/getters) void setBalance(double balance); void setInterestRate(double rate); double getBalance(); double getInterestRate(); string getAccount(); // Public method interface double makeDeposit(double deposit); double makeWithdrawl(double withdrawl); double makeTransfer(double transfer, BankAccount& other); double addAccruedInterest(); string issueMonthlyStatement(int month, int year); private: // Constants that apply to the whole class static const char DEPOSIT = 'D'; static const char WITHDRAWL = 'W'; static const char INTEREST = 'I'; static const char OVERDRAFT = 'O'; static const char TRANSFER = 'T'; // Private utility methods Transaction shrink_wrap(string src_acct, char type, double amount, time_t date=0); Transaction shrink_wrap(string src_acct, char type, double amount, string dst_acct, time_t date=0); void record_transaction(string src_acct, char type, double amount); void record_transaction(string src_acct, char type, double amount, string dst_acct); time_t monthBegin(int month, int year); time_t monthEnd(int month, int year); bool isLeapYear(int year); // Instance variables string account; double balance; double interest_rate; vector transactions; }; int main() { BankAccount myAccount; } /******************************************************************************** * * Constructors for BankAccount * *******************************************************************************/ /* * Default constructor initializes all to 0.0 */ BankAccount::BankAccount() : balance(0.0), interest_rate(0.0) { } BankAccount::BankAccount(double bal, double rate) { balance = bal; interest_rate = rate; } /******************************************************************************** * * PUBLIC interface implementation * *******************************************************************************/ /* * makeDeposit(double deposit) = adds deposit to balance, creates transaction */ double BankAccount::makeDeposit(double deposit) { record_transaction(account, DEPOSIT, deposit); return (balance += deposit); } /* * makeWithdrawl(double withdrawl) = subtracts withdrawl from balance, creates transaction * will only happen if balance > withdrawl amount. */ double BankAccount::makeWithdrawl(double withdrawl) { if (balance >= withdrawl) { record_transaction(account, WITHDRAWL, withdrawl); return (balance -= withdrawl); } record_transaction(account, OVERDRAFT, withdrawl); cerr << "Error: cannot make withdrawl unless you get overdraft.\n"; return balance; } /* * makeTransfer(double transfer, BankAccount& other) = makes withdrawl from this * and deposit to other, creates transaction */ double BankAccount::makeTransfer(double transfer, BankAccount& other) { double oldBalance = balance; double newBalance = makeWithdrawl(transfer); // if (oldBalance == newBalance) { cerr << "Error: insufficient funds for transfer.\n"; return oldBalance; } other.makeDeposit(transfer); record_transaction(account, TRANSFER, transfer, other.getAccount()); return balance; } /* * addAccruedInterest() = calculates the monthly interest * adds it to the balance. */ double BankAccount::addAccruedInterest() { double fraction_rate = interest_rate/100.0; double interest = balance * fraction_rate/12.0; balance += interest; record_transaction(account, INTEREST, interest); return balance; } /* * string issueMonthlyStatement() */ string BankAccount::issueMonthlyStatement(int month, int year) { time_t begTime = monthBegin(month-1, year); time_t endTime = monthEnd(month-1, year); string month_trans; for (vector::iterator it = transactions.end(); it != transactions.begin() && (*it).date.time >= begTime; it--) { if ( (*it).date.time >= begTime && (*it).date.time <= endTime ) { month_trans += (*it).type + " " + (*it).src_account + " " + to_string((*it).amount) + " " + ctime(&(*it).date.time); if ((*it).type == 'T') month_trans += (*it).dst_account + "\n"; else month_trans += "\n"; } } return month_trans; } /******************************************************************************** * * PUBLIC accessor/mutator member functions * *******************************************************************************/ /* * string getAccount() - returns the account number * */ string BankAccount::getAccount() { return account; } /* * double getBalance() - returns balance */ double BankAccount::getBalance() { return balance; } /* * double getInterestRate() - returns interest */ double BankAccount::getInterestRate() { return interest_rate; } /* * void setBalance(double newBalance) - sets balance */ void BankAccount::setBalance(double newBalance) { balance = newBalance; } /* * void setInterestRate(double newRate) - sets interest */ void BankAccount::setInterestRate(double newRate) { interest_rate = newRate; } /******************************************************************************** * * PRIVATE member functions * *******************************************************************************/ /* * record_transaction(char type, double amount); * @param src_account: a string for source account * @param type: a char for transaction type * @param amount: a double for amount * @returns void */ void BankAccount::record_transaction(string src_account, char type, double amount) { switch (type) { case DEPOSIT: case WITHDRAWL: case INTEREST: case OVERDRAFT: transactions.push_back(shrink_wrap(src_account, type, amount, time(NULL))); break; default: cerr << "Error: no such transaction type: " << type << endl; } } /* * record_transaction(string src_account, char type, double amount, string dst_account) * @param src_account: a string for source account * @param type: a char for transaction type * @param amount: a double for amount * @param dst_account: a string for destination account. * @returns void */ void BankAccount::record_transaction(string src_account, char type, double amount, string dst_account) { if (type != TRANSFER) { cerr << "Error: incorrect transaction type: " << type << endl; return; } transactions.push_back(shrink_wrap(src_account, type, amount, dst_account, time(NULL))); } /* * shrink_wrap - packages a transaction given a the following parameters * @param src_account: a string for source account * @param type: a char for transaction type * @param amount: a double for amount * @param time: a time_t for time * @returns a Transaction struct. */ Transaction BankAccount::shrink_wrap(string src_acct, char type, double amount, time_t t) { Transaction temp; temp.src_account = src_acct; temp.type = type; temp.amount = amount; temp.date.time = t; return temp; } /* * shrink_wrap - packages a transaction given a the following parameters * @param src_account: a string for source account * @param type: a char for transaction type * @param amount: a double for amount * @param dst_account: a string for destination account. * @param time: a time_t for date * @returns a Transaction struct. */ Transaction BankAccount::shrink_wrap(string src_acct, char type, double amount, string dst_account, time_t t) { Transaction temp; temp.src_account = src_acct; temp.type = type; temp.amount = amount; temp.date.time = t; temp.dst_account = dst_account; return temp; } /* * bool isLeapYear(year) - calculate if feb has 28 or 29 days. */ bool BankAccount::isLeapYear(int year) { return ((year % 4)==0) ? (((year % 100)==0) ? (((year % 400)==0) ? true : false) : true) : true; } /* * time_t monthBegin(int month, int year) * */ time_t BankAccount::monthBegin(int month, int year) { struct tm beg_time = { 0, 0, 0, 1, month, year - 1900 }; return mktime(&beg_time); } /* * time_t monthEnd(int month, int year) */ time_t BankAccount::monthEnd(int month, int year) { static int daysPerMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; struct tm end_time = { 59, 59, 23, daysPerMonth[month], year - 1900 }; // Handle February and leap years int days = daysPerMonth[month-1]; if (days == 28 && isLeapYear(year)) { end_time.tm_mday = 29; } return mktime(&end_time); }