小项目之个人银行账户管理程序(5)

在基类Account中将账户的公共操作皆声明为虚函数,因此可以通过基类的指针来执行各种操作,因而各种类型的账户对象都可以通过一个指针的数组来访问。

//date.h
#ifndef _DATE_H_
#define _DATE_H_
class Date//日期类
{
private:
	int year;
	int month;
	int day;
	int totalDays;//该日期是从公元元年1曰1日开始的第几天

public:
	Date(int year,int month,int day);//用年月日构造日期
	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;
	}
};
#endif

//date.cpp
#include"date.h"
#include<cstdlib>
#include<iostream>
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())
	{
		cout<<"Invalid date: ";
		show();
		cout<<endl;
		exit(1);
	}
	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();
}

//accumulator.h
#ifndef _ACCUMULATOR_H_
#define _ACCUMULATOR_H_
#include"date.h"
class Accumulator//将某个数值按日累加
{
private:
	Date lastdate;//上次变更数值的日期
	double value;//数值的当前值
	double sum;//数值按日累加之和
public:
	//构造函数,date为开始累加的日期,value为初始值
	Accumulator(const Date &date,double value):lastdate(date),value(value),sum(0)
	{}
	//获得日期date的累加结果
	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;
	}
};

#endif

//account.h

#ifndef _ACCOUNT_H_
#define _ACCOUNT_H_
#include"date.h"
#include"accumulator.h"
#include<string>
#include<iostream>
using namespace std;
class Account //账户类
{
private:
	string id;//账号
	double balance;//余额
	static double total;//所有账户的总金额
protected:
	//供派生类调用的构造函数,id为账户
	Account(const Date &date,const string &id);
	//记录一笔账,日期,金额,说明
	void record(const Date &date,double amount,const string &desc);
	//报告错误信息
	void error(const string &msg)const;
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;
	//取出现金
	virtual void withdraw(const Date &date,double amount,const string &desc)=0;
	//结算(计算利息、年费),每月结算一次,date为结算日期
	virtual void settle (const Date &date)=0;
	virtual void show()const;
};
class SavingsAccount:public Account//储蓄账户类
{
private:
	Accumulator acc;//辅助计算利息的累加器
	double rate;//存款年利率

public:
	SavingsAccount(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 dmount,const string &desc);//取出现金
	void settle(const Date &date);//结算利息,每年1月1日调用一次该函数	
};
class CreditAccount:public Account//信用账户类
{
private:
	Accumulator acc;//辅助计算利息的累加器
	double credit;//信用额度
	double rate;//欠款的日利率
	double fee;//信用卡年费
	double getDebt()const//获得欠款额
	{
		double balance=getBalance();
		return (balance<0 ? balance:0);
	}
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 dmount,const string &desc);//取出现金
	void settle(const Date &date);//结算利息和年费,每月1日调用一次该函数	
	void show()const;

};
#endif

//account.cpp
#include"account.h"
#include<cmath>
#include<iostream>
using namespace std;
double Account::total=0;
Account::Account(const Date &date,const string &id):id(id),balance(0)
{
	date.show();
	cout<<"\t#"<<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<<"\t#"<<id<<"\t"<<amount<<"\t"<<balance<<"\t"<<desc<<endl;
}
void Account::show()const
{
	cout<<id<<"\tBalance: "<<balance;
}
void Account::error(const string &msg)const
{
	cout<<"Error(#"<<id<<"):"<<msg<<endl;
}


SavingsAccount::SavingsAccount(const Date &date,const string &id,double rate):Account(date,id),rate(rate),acc(date,0)
{}

void SavingsAccount::deposit(const Date &date,double amount,const string &desc)
{
	record(date,amount,desc);
	acc.change(date,getBalance());
}
void SavingsAccount::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 SavingsAccount::settle(const Date &date)
{
	if(date.getMonth()==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());
	}
}

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 money");
	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()const
{
	Account::show();
	cout<<"\tAvailable credit:"<<getAvailableCredit();
}

//main.cpp
#include"account.h"
#include<iostream>
using namespace std;
int main()
{
	Date date(2008,11,1);//起始日期
	//建立几个账户
	SavingsAccount sa1(date,"s3755217",0.015);
	SavingsAccount sa2(date,"02342342",0.015);
	CreditAccount ca(date,"C5392394",10000,0.0005,50);
	Account * accounts[]={&sa1,&sa2,&ca};
	const int n=sizeof(accounts)/sizeof(Account*);//账户总数
	cout<<"(d)deposit(w)withdraw(s)show(c)change day(n)next month(e)exit"<<endl;
	char cmd;
	do{
		date.show();
		cout<<"\tTotal: "<<Account::getTotal()<<"\tcommand>";
		int index,day;
		double amount;
		string desc;
		cin>>cmd;
		switch(cmd)
		{
		case 'd':
			cin>>index>>amount;
			getline(cin,desc);
			accounts[index]->deposit(date,amount,desc);
			break;
		case 'w':
			cin>>index>>amount;
			getline(cin,desc);
			accounts[index]->withdraw(date,amount,desc);
			break;
		case 's':
			for(int i=0;i<n;++i)
			{
				cout<<"["<<i<<"]";
				accounts[i]->show();
				cout<<endl;
			}
				break;
		case 'c':
			cin>>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);
			break;
		case 'n':
			if(date.getMonth()==12)
				date=Date(date.getYear()+1,1,1);
			else
				date=Date(date.getYear(),date.getMonth()+1,1);
			for(int i=0;i<n;++i)
				accounts[i]->settle(date);
			break;
		}
	}while (cmd!='e');
	
	return 0;
}


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值