这个程序是一个银行账户管理的程序,是用C++来实现程序功能的,该程序包含六个文件,其中有date.h头文件
是日期类的头文件,date.cpp是日期类的实现文件,accumulator.h是按日将数值累加的accumulator类的头文件,
account.h是各个储蓄账户类定义的头文件,account.cpp是各个储蓄账户类的实现文件,还有就是主函数文件。该
程序包含了增加账户功能、存款功能、取款功能、查询账户信息功能、改变日期功能、进入下个月的处理功能,最
后是退出程序。下面是各个程序文件:
1.date.h日期类的头文件
#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; //获得当月有多少天 bool isLeapYear() const //判断当年是否为闰年 { return year % 4 == 0 && year % 100 != 0 && year % 400 == 0; } void show()const; //输出当前日期 int operator-(const Date &date)const //计算两个日期之间差多少天 { return totalDays - date.totalDays; } bool operator<(const Date &date)const //判断两个日期的前后顺序 { return totalDays < date.totalDays; } private: int year; int month; int day; int totalDays; //该日期是从公元元年1月1日开始的第几天 }; istream& operator >> (istream &in, Date &date); ostream& operator << (ostream &out, const Date &date); #endif
2.date.cpp日期类实现的文件
#include <iostream> #include <stdexcept> #include "date.h" using namespace std; namespace //namespace使下面的定义只在当前文件中有效 { //存储平年中的某个月1日之前有多少天,为便于getMaxDay函数的实现,该数组多出一项 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按日将数值累加的头文件
#ifndef _ACCUMULATOR_H #define _ACCUMULATOR_H #include "date.h" class Accumulator //将某个数值按日累加 { public: //date为开始累加的日期,value为初始值 Accumulator(const Date &date, double value):lastDate(date),value(value),sum(0) { } double getSum(const Date &date)const { return sum + value*(date - lastDate); } //在date将数值变更为value void change(const Date &date, double value) { sum = getSum(date); lastDate = date; this->value = value; } //初始化,将日期变为date,数值变为value,累加器清零 void reset(const Date &date, double value) { lastDate = date; this->value = value; sum = 0; } private: Date lastDate; //上次变更数值的时期 double value; //数值的当前值 double sum; //数值按日累加之和 }; #endif
4.account.h各个储蓄账户类定义的头文件
#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 //账目记录 { public: AccountRecord(const Date &date, const Account* account, double amount, double balance, const string &desc); void show()const; //输出当前记录 private: Date date; //日期 const Account* account; //账户 double amount; //金额 double balance; //余额 string desc; //描述 }; typedef multimap<Date, AccountRecord> RecordMap; //账户类 class Account { public: const string& getId()const { return id; } double getBalance()const { return balance; } static double getTotal() { return total; } //存入现金,date为日期,amount为金额,desc为款项说明 virtual void deposit(const Date &date, double amount, const string &desc) = 0; //取出现金,date为日期,amount为金额,desc为款项说明 virtual void withdraw(const Date &date, double amount, const string &desc) = 0; //结算,每月结算一次,date为结算日期 virtual void settle(const Date &date) = 0; //显示账户信息 virtual void show(ostream &out)const; //查询指定时间内的账目记录 static void query(const Date &begin, const Date &end); protected: //供派生类调用的构造函数 Account(const Date &date, const string &id); //记录一笔账,date为日期,amount为金额,desc为说明 void record(const Date &date, double amount, const string &desc); //报告错误信息 void error(const string &msg)const; private: string id; //账户 double balance; //余额 static double total; //所有账户的总金额 static RecordMap recordMap; //账目记录 }; inline ostream& operator<<(ostream &out, const Account &account) { account.show(out); return out; } class SavingAccount :public Account //储蓄账户类 { public: SavingAccount(const Date &date, const string &id, double rate); double getRate()const { return rate; } //存入现金 void deposit(const Date &date, double amount, const string &desc); //取出现金 void withdraw(const Date &date, double amount, const string &desc); //结算利息,每年1月1日调用一次该函数 void settle(const Date &date); private: Accumulator acc; //辅助计算利息的累加器 double rate; //存款的年利率 }; class CreditAccount :public Account //信用账户类 { 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 //获得可用信用额度 { if (getBalance() < 0) return credit + getBalance(); else return credit; } //存入现金 void deposit(const Date &date, double amount, const string &desc); //取出现金 void withdraw(const Date &date, double amount, const string &desc); //结算利息和年费,每月1日调用一次该函数 void settle(const Date &date); virtual void show(ostream &out)const; private: Accumulator acc; //辅助计算利息的累加器 double credit; //信用额度 double rate; //欠款的日利率 double fee; //信用卡年费 double getDebt() const //获得欠款额 { 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.account.cpp各个储蓄账户类的实现文件
#include <iostream> #include <cmath> #include <utility> #include "account.h" using namespace std; using namespace std::rel_ops; //AccountRecord类的实现 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 << " #" << account->getId() << " " << amount << " " << balance << " " << desc << endl; } //Account类的实现 double Account::total = 0; RecordMap Account::recordMap; Account::Account(const Date &date, const string &id):id(id),balance(0) { cout << date << " #" << id << " created" << endl; } void Account::record(const Date &date, double amount, const string &desc) { amount = floor(amount * 100 + 0.5) / 100; //保留小数点后两位 balance += amount; total += amount; date.show(); cout << " #" << id << " " << amount << " " << balance << " " << desc << endl; } void Account::show(ostream &out)const { out << id << " Balance: " << 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类的实现 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 << " Available credit: " << getAvailableCredit(); } //SavingAccount类的实现 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) //每年的1月计算一次利息 { 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.主函数文件
#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; } }; //控制器类,用来存储账户列表和处理命令 class Controller { public: Controller(const Date &date) :date(date), end(false) { } ~Controller(); const Date& getDate()const { return date; } bool isEnd()const { return end; } //执行一条命令,返回该命令是否改变了当前状态(即是否需要保存当前命令) bool runCommand(const string &cmdLine); private: Date date; vector<Account*> accounts; //账户列表 bool end; //用户是否输入了退出命令 }; 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': //增加账户 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': //存入现金 str >> index >> amount; getline(str, desc); accounts[index]->deposit(date, amount, desc); return true; case 'w': //取出现金 str >> index >> amount; getline(str, desc); accounts[index]->withdraw(date, amount, desc); return true; case 's': //查询各账户信息 for (size_t i = 0;i < accounts.size();++i) { cout << "[" << i << "]"; accounts[i]->show(cout); cout << endl; } return false; case 'c': //改变日期 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': //进入下个月 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': //查询一段时间内的账目 str >> date1 >> date2; Account::query(date1, date2); return false; case 'e': //退出 end = true; return false; } cout << "Invalid command: " << cmdLine << endl; return false; } int main() { Date date(2018, 1, 1); //起始日期 Controller controller(date); string cmdLine; const char *FILE_NAME = "commands.txt"; ifstream fileIn(FILE_NAME); //以读模式打开文件 if (fileIn) //如果正常打开,就执行文件中的每一条命令 { while (getline(fileIn, cmdLine)) controller.runCommand(cmdLine); fileIn.close(); } ofstream fileOut(FILE_NAME, ios_base::app); //以追加模式打开文件 cout << "(a)add account (d)deposit (w)withdraw (s)show (c)change day (n)next month (q)query (e)exit" << endl; while (!controller.isEnd()) //从标准输入读入命令并执行,直到退出 { cout << controller.getDate() << " Total: " << Account::getTotal() << " command"; string cmdLine; getline(cin, cmdLine); if (controller.runCommand(cmdLine)) fileOut << cmdLine << endl; //将命令写入文件 } return 0; }
最后运行主函数将程序功能实现,可以进行增加账户功能、存款功能、取款功能、查询账户信息功能、改变日期功
能、进入下个月的处理功能将程序进行操作,最后附上一张我操作这些功能的截图。