当前位置: 首页 > 编程日记 > 正文

个人银行账户管理程序

  这个程序是一个银行账户管理的程序,是用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;elsereturn 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将数值变更为valuevoid 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();elsereturn 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 << "\t#" << account->getId() << "\t" << amount << "\t" << balance << "\t" << desc << endl;
}//Account类的实现
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;      //保留小数点后两位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类的实现
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类的实现
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";elsedate = Date(date.getYear(), date.getMonth(), day);return true;case 'n':               //进入下个月if (date.getMonth() == 12)date = Date(date.getYear() + 1, 1, 1);elsedate = 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() << "\tTotal: " << Account::getTotal() << "\tcommand";string cmdLine;getline(cin, cmdLine);if (controller.runCommand(cmdLine))fileOut << cmdLine << endl;          //将命令写入文件
    }return 0;
}

   最后运行主函数将程序功能实现,可以进行增加账户功能、存款功能、取款功能、查询账户信息功能、改变日期功

进入下个月的处理功能将程序进行操作,最后附上一张我操作这些功能的截图。

       

转载于:https://www.cnblogs.com/XNQC1314/p/9011891.html

相关文章:

两个关于水花的测试。

海面上的水花的特效&#xff0c;水花是在浪尖处发射出来的&#xff0c;目前还没有让发射参数自动化的方法&#xff0c;都是表达式。一旦改变浪的性质&#xff0c;发射的粒子就要重新写动态了。 Splash on the ocean emitted from the crisp faces on top of the wave, the whit…

泛型在三层中的应用

一说到三层架构&#xff0c;我想大家都了解&#xff0c;这里就简单说下&#xff0c;三层架构一般包含&#xff1a;UI层、DAL层、BLL层&#xff0c;其中每层由Model实体类来传递&#xff0c;所以Model也算是三层架构之一了&#xff0c;例外为了数据库的迁移或者更OO点&#xff0…

【蓝桥java】进制与整除之尼姆堆

题目&#xff1a; 有3堆硬币&#xff0c;分别是3,4,5 二人轮流取硬币。 每人每次只能从某一堆上取任意数量。 不能弃权。 取到最后一枚硬币的为赢家。 求先取硬币一方有无必胜的招法。 在提供代买前做几条补充&#xff1a; &#xff08;1&#xff09;这里有一个不是很好理解的…

RSA遭骇 Token 换?不换?

RSA SecurID Token召回更换的动作仍然持续进行中&#xff0c;根据外电报导&#xff0c;美国有些企业已经要求更换Token&#xff0c;如花旗集团、美国银行、富国银行、摩根大通、澳盛银行、澳洲西太平洋银行。于此同时&#xff0c;一些竞争供应商也动作频频&#xff0c;例如Safe…

二叉树的镜像(数组,前后 遍历重建二叉树)

题目描述 操作给定的二叉树&#xff0c;将其变换为源二叉树的镜像。输入描述: 二叉树的镜像定义&#xff1a;源二叉树 8/ \6 10/ \ / \ 5 7 9 11镜像二叉树8/ \10 6/ \ / \11 9 7 5 #include <iostream> #include <cstdio> #include <cstdlib> #in…

tp5实现Redis的简单使用

方法1&#xff1a; Controller <?php namespace app\index\controller;use think\Controller; use think\session\driver\Redis;class Index extends Controller {public function index(){$redis new Redis();if(!$redis->has(str)){var_dump($redis->set(str,this…

Linux下getsockopt/setsockopt 函数说明

【getsockopt/setsockopt系统调用】 功能描述&#xff1a; 获取或者设置与某个套接字关联的选 项。选项可能存在于多层协议中&#xff0c;它们总会出现在最上面的套接字层。当操作套接字选项时&#xff0c;选项位于的层和选项的名称必须给出。为了操作套接字层的选项…

【蓝桥java】进制与整除之最大公约数 最小公倍数

补充&#xff1a; &#xff08;1&#xff09;欧几里得定理&#xff08;辗转相除法&#xff09;&#xff1a;A和B的最大公约数 B和A%B 的最大公约数 &#xff08;2&#xff09;将两个数乘起来再除以最大公约数就是最小公倍数 package cn.zzunit.jnvi;/***寻找最大公约数* autho…

学习C#要养成的好习惯

1. 避免将多个类放在一个文件里面。2. 一个文件应该只有一个命名空间&#xff0c;避免将多个命名空间放在同一个文件里面。3. 一个文件最好不要超过500行的代码&#xff08;不包括机器产生的代码&#xff09;。4. 一个方法的代码长度最好不要超过25行。5. 避免方法中有超过5个参…

3.1、final、finally、 finalize

final 可以用来修饰类、方法、变量&#xff0c;分别有不同的意义&#xff0c;final 修饰的 class 代表不可以继承扩展&#xff0c;final 的变量是不可以修改的&#xff0c;而 final 的方法也是不可以重写的&#xff08;override&#xff09;。 finally 则是 Java 保证重点代码一…

Android模拟器学framework和driver之传感器篇1(linux sensor driver)

对于android模拟器开发环境的搭建这里我就不多说了&#xff0c;网上google下一大堆&#xff0c;还有就是android 模拟器的kernel使用的是goldfish的kernel&#xff0c;可以使用git得到源码&#xff0c;然后就可以编译了&#xff0c;大家还是可以参考罗老师的博客。。。 在这里我…

【java】Lombok的使用

介绍&#xff1a;lombok在编译entity文件时自动生成get set toString hashCode等方法&#xff0c;这样方法生成就不用写在代码里了&#xff0c;可以简化代码。 使用方法&#xff1a; 一、在pom文件里引入lombok的依赖 代码实现&#xff1a; <dependency><groupId&g…

自己开发开源jquery插件--给jquery.treeview加上checkbox

很多时候需要把树状的数据显示除来&#xff0c;比如分类&#xff0c;中国省份、城市信息&#xff0c;等&#xff0c;因此这方面的javascript插件也有很多.比如性能优异的jquery.treeview和国人开发的功能强大的zTree. 我最近在一个项目中用到了jquery.treeview&#xff0c;但是…

SQL Server 2000安装时不出现安装界面,进程中存在解决

在XP和Server 2003系统中安装SQL Server 2000过程中&#xff0c;点击安装后&#xff0c;一直不出现安装界面&#xff0c;查看进程中也有&#xff0c;一直无反应。 解决办法&#xff1a; 首先重新启动机器&#xff0c;或者任务管理器里面结束2个sql进程 1. 在 SQLServer 安装向导…

Apache2.4部署python3.6+django2.0项目

一、安装apache Apache是非常有名的web服务器软件&#xff0c;如果想让我们web项目运行几乎离不开它。 Apache官方网站&#xff1a;http://httpd.apache.org/ 根据自己的环境&#xff0c;选择相应的版本进行下载。apache 官网没有windows 64位版本&#xff0c;可以通过下面的链…

我是如何有效的避免测试漏测?

漏测&#xff0c;指在产品缺陷在测试过程中没有被发现&#xff08;尤其是测试环境可以重现的缺陷&#xff09;&#xff0c;而是在版本发布后或者在用户使用后发现并反馈回来的缺陷。可以说&#xff0c;漏测的问题是测试管理者最头痛的问题。因为出现漏测&#xff0c;一来给客户…

总结是学习最好的方式(转)

总结是学习最好的方式 最近一直想总结来华为公司这3个多月自己有什么收获&#xff0c;但又想不明白自己收获了什么&#xff1f;说技术吧&#xff0c;也谈不上有多大的提高&#xff1b;说人际交流&#xff0c;也许还有些退步&#xff1b;说薪资存款吧&#xff0c;哎不谈了。想着…

【转载】JUnit各个注解的含义

转自&#xff1a;https://blog.csdn.net/weixin_38500014/article/details/84393775

silverlight、wpf中 dispatcher和timer区别

相同点&#xff1a;都是定时执行任务的计时器&#xff0c;都可以使用。 不同点&#xff1a;Timer运行在非UI 线程&#xff0c;如果Timer需要更新UI的时候&#xff0c;需要调用 Invoke或者 BeginInvoke DispatcherTimer运行在UI 线程&#xff0c;处理的 Dispatcher 队列中的计时…

web开发基础

web开发:所谓web开发就是基于浏览器服务器的开发下面将web开发基础知识作个总结:1.http协议:是建立在TCP协议上的,基于请求响应的模型2.http请求:面试题:说说get与post的区别a.传递数据量:get只能传递1kb以下的数据,post可以传递大数据b.安全性:get请求,如果携带参数,参数会直接…

让ubuntu下的eclipse支持GBK编码

原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://leaze.blog.51cto.com/83088/195584今天&#xff0c;把windows下的工程导入到了Linux下eclipse中&#xff0c;由于以前的工程代码&#x…

Session,ViewState用法

Session,ViewState用法基本理论&#xff1a; session值是保存在服务器内存上,那么,可以肯定,大量的使用session将导致服务器负担加重. 而viewstate由于只是将数据存入到页面隐藏控件里,不再占用服务器资源,因此, 我们可以将一些需要服务器"记住"的变量和对象保存到vi…

【HTML】记录自己丢人过程:文本换行缩进都不会

问题描述&#xff1a; html文本想实现换行和缩进&#xff0c;最后气到摔鼠标 换行 实现代码&#xff1a; <br> 直接在文本后加个换行标签即可 缩进 实现代码&#xff1a; style"text-indent: 2em;" 注意&#xff1a;这个属性放到p标签中或者div标签中都…

CentOS5.6系统下mysql5安装

我的系统是CentOS5.6 建议大家完全安装&#xff0c;以免安装时缺少相关的编译器等等。 一、安装mysql&#xff08;mysql-5.1.50.tar.gz&#xff09; # tar zxf mysql-5.1.50.tar.gz # cd mysql-5.1.50 #./configure --prefix/usr/local/mysql --sysconfdir/etc --localstated…

CentOS 6.9/7通过yum安装指定版本的JDK/Maven

说明&#xff1a;通过yum好处其实很多&#xff0c;环境变量不用配置&#xff0c;配置文件放在大家都熟悉的地方&#xff0c;通过rpm -ql xxx可以知道全部文件的地方等等。 一、安装JDK&#xff08;Oracle JDK 1.8&#xff09; # wget --no-check-certificate --no-cookies --he…

2019牛客全国多校训练三 题解

A Gragh Games Unsolved. B Crazy Binary String 题解&#xff1a;水题&#xff0c;子序列只要统计0和1数量&#xff0c;取最小值然后乘2就是答案&#xff1b; 对于子串&#xff1a;先记录0和1 前缀和的差值&#xff0c;然后找差值相等的距离最远的两个位置即可&#xff1b; 参…

【硬件基础】有源蜂鸣器与无源蜂鸣器

辨别方法 外观&#xff1a; 无源蜂鸣器: 有源蜂鸣器&#xff1a; 注&#xff1a;可以看到底部有绿色电路板的是无源蜂鸣器&#xff0c;底部是黑胶的为有源蜂鸣器 万用表电阻档检测 无源蜂鸣器&#xff1a;发出咔、咔声的且电阻只有8Ω&#xff08;或16Ω&#xff09;。 有源…

hdu 1272 小希的迷宫

Problem Description上次Gardon的迷宫城堡小希玩了很久&#xff08;见Problem B&#xff09;&#xff0c;现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样&#xff0c;首先她认为所有的通道都应该是双向连通的&#xff0c;就是说如果有一个通道连通了房间A和B…

技术还是商业重要

在中国IT业创业听得最多的就是&#xff0c;技术不重要&#xff0c;商业和关系才是最重要的。 到了硅谷之后&#xff0c;发现技术气氛十分浓&#xff0c;甚至有朋友说大陆创业比较容易是因为硅谷与之相比&#xff0c;硅谷太注重技术了。 可是慢慢发现其实在硅谷&#xff0c;商业…

bzoj1036: [ZJOI2008]树的统计Count 树链剖分

一棵树上有n个节点&#xff0c;编号分别为1到n&#xff0c;每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作&#xff1a; I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的…