求打赏求收藏求转发!
提供PDF资源
https://download.csdn.net/download/weixin_43781565/12429058
(审核后可供下载)
Peace and love
一、实验名称
模拟银行柜员机(ATM)的控制台指令实现
本次实验旨在对前期学习的有关C++面向对象模块相关知识进行实际操作,将理论联系实际,提升面向对象部分的代码实现能力。
在理论方面主要体现了:
- 训练由面向过程向面向对象的思维转变;
- 加深对类(class)的概念和面向对象编程(OOP)的理解;
- 提升对类中成员函数(member function)和数据成员(data member)与需求之间的抽象能力;
在实际操作方面,本次试验重点训练了:
- 类(class)的创建与其中三种访问修饰符(public/protected/private)的应用,以及多个类之间的互相调用访问;
- 类中构造函数和析构函数的实现;
- 数据成员和成员函数的声明,创建和调用;
- 对象的创建和使用
IDE :CodeBlocks16.1 (Core:VC++6.0)
Language Standard : C++14
自动柜员机ATM(Automatic Teller Machine),是一个实用而高效的利用磁性代码卡或智能卡实现金融交易的自助服务机器,以代替银行柜面人员的工作。众所周知,银行,是我们每个人在生活中都要接触的公共服务,而ATM的机的出现,使人们在银行关门的时段对银行部分服务的需求得以满足。
因此对于ATM机执行程序的设计变得尤为重要,一个实用而高效的ATM机器可以极大地方便用户的使用。
对于ATM机器的设计,可以通过实际生活中的分析,总结出ATM机执行程序实际中应该包含的常用功能如下:
除了程序的基本功能之外,对于使用ATM机的用户(Consumer)来说,它也需要以下的几个属性设置:
对于ATM在实现部分功能时,通过需求分析可知,部分功能的内部代码部分是相同或类似的,如存款/取款中对钱(money)的加减操作,或如对密码(passwd)的修改(change),获取(get)和保存(set)等各项操作,需要部分的隐性成员函数来实现,所以在ATM类中同时需要部分的成员函数在用来优化代码成本的同时,可以减少主函数(main())中的代码量,做到部分代码分离(separation).
而对于Consumer类中,需要对数据成员的类型进行分析,大部分的数据是需要被放置在protected或private进行保护的.此外,有关数据成员操作的函数,也应该在其中被声明
最后应该让ATM类和Consumer类可以作为has的类型关联起来.
根据需求的分析,首先得到ATM机的大致操作流程,用流程图表示如下:
并参考需求分析中的要求,并结合相关内容,确定出ATM类中的成员函数和数据成员,ATM类代码片段如下:
备注:其中加粗函数名为隐性函数,目的是达到需求分析中的减少主函数(main())中的代码量并做到代码分离(separation).
- class ATM
- {
- public:
- ATM(consumer & cn):cnsm(cn){}
- void welcome(); //欢迎界面
- bool check_passwd(string num,string pwd); //核对密码
- void change_passwd(); //修改密码
- void fetchmoney(); //取款
- void deposit(); //存款
- void information(); //查询信息
- void exitATM(); //退出系统
- void functionshow(); //功能界面
- void transfer(); //转账
- void lock(); //锁机
- private:
- int times; //记录密码输入错误次数,为lock()函数作判断条件
- consumer &cnsm;
- };
Consumer类代码片段如下:
- class consumer //用户
- {
- public:
- friend class ATM;
- consumer(string Name,string Kahao,float Money,string Password);
- protected:
- string get_name(); //取得姓名
- string get_kahao(); //取得卡号
- string get_passwd(); //取得密码
- float get_money(); //取得余额
- void set_passwd(string pwd); //设置密码
- void set_money(int sign,float m);
- //关于money的存/取款操作
- private:
- string passwd; //用户密码
- string name; //用户姓名
- string kahao; //用户卡号
- float money; //用户余额
- };
其中,根据相关的需求分析我们可知,将密码,用户姓名,卡号与余额等敏感信息应保护在private中,而对于在ATM中的相关操作的成员函数应放在protected中
为了测试方便,需要提前在consumer中创建一个name为”孙嘉成”的账户,并设置缺省金额,卡号,密码等信息.利用构造函数进行初始化,并在main()中运行时调用.
consumer构造函数如下:
- consumer::consumer(string Name,string Kahao,float Money,string Password)
- //构造函数,建立账户
- {
- name=Name;
- kahao=Kahao;
- money=Money;
- passwd=Password;
- }
由于前期的代码简化和函数分离,主函数main中的代码段大量减少,main函数代码片段如下:
- int main()
- {
- consumer c1("孙嘉成","123456",10000.00F,"666888");
- //创建一个用户,作为测试用例
- ATM atm(c1); //创建一个ATM对象
- atm.welcome(); //调用登录函数,启动ATM机
- return 0;
- }
对于实现功能的成员函数,具体代码如下:
- 取款(fetchmoney);
- void ATM::fetchmoney()
- {
- int m; //接收输入金额
- char ch; //接收操作数
- do
- {
- cout<<endl<<"请输入取款金额:(1.每次最多操作5000元;2.取款金额为100的倍数)"<<"\n$>\\";
- cin>>m;
- while(m<=0)
- {
- cout<<"请输入正确的数字!"<<endl;
- cout<<"$>\\";
- cin>>m;
- }
- if(m>5000)
- {
- cout<<"对不起,每次操作最多5000元"<<endl;
- }
- else
- {
- if((int)m%100!=0)
- {
- cout<<"对不起,取款金额为100的倍数"<<endl;
- }
- else
- {
- if(cnsm.get_money()-m<0)
- {
- cout<<"对不起,余额不足!"<<endl;
- }
- else
- {
- cout<< endl<<"操作成功!" <<endl;
- int sign = 0;
- cnsm.set_money(sign,m);
- }
- }
- }
- cout<<"是否要继续此操作:(Y/N)"<<endl;
- cout<<"$>\\";
- cin>>ch;
- while(ch!='n'&&ch!='Y'&&ch!='y')
- {
- cout<<"$>\\";
- cin>>ch;
- }
- }while(ch=='y'||ch=='Y');}
- 查询余额(information);
- void ATM::information() //信息页面
- {
- cout<<"**************************"<<endl;
- cout<<"*"<<endl;
- cout<<"* 用户姓名:"<<cnsm.get_name()<<endl;
- cout<<"* 卡号: "<<cnsm.get_kahao()<<endl;
- cout<<"* 余额: "<<cnsm.get_money()<<endl;
- cout<<"**************************"<<endl;
- }
- 存款(deposit);
代码大部分注释同取款(fetchmoney)操作,此处不再赘述
- void ATM::deposit()
- {
- int m;
- char ch;
- do
- {
- cout<<endl<<"请输入存款金额:(1.每次最多操作5000元;2.存款金额为100的倍数)"<<"\n$>\\";
- cin>>m;
- while(m<=0)
- {
- cout<<"请输入正确的数字!"<<endl;
- cout<<"$>\\";
- cin>>m;
- }
- if(m>5000)
- {
- cout<<"对不起,每次操作最多5000元"<<endl;
- }
- else
- {
- if((int)m%100!=0)
- {
- cout<<"对不起,存款金额为100的倍数"<<endl;
- }
- else
- {
- cout<< endl<<"操作成功!" <<endl;
- int sign = 1;
- cnsm.set_money(sign,m);
- }
- }
- cout<<"是否要继续此操作:(Y/N)"<<endl;
- cout<<"$>\\";
- cin>>ch;
- while(ch!='n'&&ch!='Y'&&ch!='y')
- {
- cout<<"$>\\";
- cin>>ch;
- }
- }while(ch=='y'||ch=='Y');}
- 修改密码(change_passwd);void ATM::change_passwd(){
- string pwd,repwd; //接收旧密码和新密码
- times=0; //统计密码出错次数
- do
- {
- cout<<endl<<"请输入旧密码:";
- cin>>pwd;
- if(!check_passwd(cnsm.get_kahao(),pwd))
- {
- times++;
- cout<<"密码输入错误!"<<endl;
- }
- else
- break;
- }while(times<3);
- if(times==3)
- lock();
- //密码错误达到3次执行锁机操作,退出程序
- int k=0; //进行密码格式限定
- int t=0; //清零计数
- do
- {
- k=0;
- cout<<"请输入新密码:";
- cin>>pwd;
- int g=0;
- int v=0;
- g=pwd.length();
- if(g<6)
- {
- k=1;
- cout<<"密码不能小于6位"<<endl;
- }
- if(g>6)
- {
- cout<<"请再输入一次新密码:";
- cin>>repwd;
- if(pwd!=repwd)
- {
- cout<<"你输入的两次密码不一样,请重新输入!"<<endl;
- }
- }
- }while(t!=0||k==1);
- cnsm.set_passwd(pwd);
- cout<<"密码修改成功,请牢记!"<<endl;}
而在成员函数的实现之中还有部分的隐性函数调用,代码片段如下:
- void ATM::welcome() //登录界面
- {
- times=0; //密码错误次数
- cout<<"*欢迎使用银行ATM自动取款机*"<<endl;
- string pwd,num,ch; //接收密码,卡号,与操作数
- do
- {
- cout<<endl<<"请输入卡号:";
- cin>>num;
- cout<<"请输入密码:";
- cin>>pwd;
- if(!check_passwd(num,pwd))
- {
- cout<<"你输入的卡号或密码有误,请重新输入"<<endl;
- times++;
- }
- else
- {
- functionshow(); //进入功能操作
- }
- }while(times<3);
- lock(); //错误次数达到三次锁机}
- void ATM::lock()
- {
- cout<<endl<<"您的错误次数过多!"<<endl;
- cout<<endl<<"感谢您的使用,请取回您的卡片,欢迎下次光临!"<<endl;
- cout<<""<<endl;
- exit(0);
- }
- void ATM::functionshow()
- {
- int n;
- do
- {
- cout <<endl<<"请输入相应的操作序号进行操作: "<<endl;
- cout<<"1)修改密码 "<<endl
- <<"2)取款 "<<endl
- <<"3)查询余额 "<<endl
- <<"4)转账 "<<endl
- <<"5)存款 "<<endl
- <<"6)退出系统 "<<endl;
- cout<<"$>\\";
- cin>>n;
- while(n<1||n>6)
- {
- cout<<"请输入正确的操作序号!"<<endl;
- cout<<"$>\\";
- cin>>n;
- }
- switch(n)
- {
- case 1: change_passwd();
- break;
- case 2: fetchmoney();
- break;
- case 3: information();
- break;
- case 4: transfer();
- break;
- case 5: deposit();
- break;
- case 6: exitATM();
- break;
- }
- }while(true);
- }
- 密码检查check_passwd(string num,string pwd);
- bool ATM::check_passwd(string num,string pwd)
- {
- if(num==cnsm.get_kahao()&& pwd==cnsm.get_passwd())
- return true; //比对卡号和密码是否正确
- else
- return false;
- }
以下为实验结果截图:
图2-2 输入密码登录以及功能页面
图2-3 查询余额并自动返回功能菜单
图2-4 取款操作,并进行测试
备注:当在”是否要继续此操作”处输入”n”或”N”是,跳转至功能页面
在本次试验操作之中,主要是对类和对象以及成员函数之间的创建,调用等方面的练习,加之对C++与C不同的特性方面的实践操作.总的来说,问题主要体现在以下几个方面:
- 类的抽象能力有待提高;虽然在需求分析的部分,对ATM和Consumer的功能已经较为全面的提出,但是在实际代码的编写部分,比如存款和取款函数中,更改了部分重复的代码,并通过添加在函数中添加sign标致符的方式去简化代码,如:
- void consumer::set_money (int sign,float m)
- {
- if(sign) //sign==0代表取款操作
- money=money-m;
- else //否则存款
- money=money+m;
- }
但是依然发现还是有很多类似或重复的代码段频繁出现.比如下面这段判断用户输入的代码:
- cout<<"是否要继续此操作:(Y/N)"<<endl;
- cout<<"$>\\";
- cin>>ch;
- while(ch!='n'&&ch!='Y'&&ch!='y')
- {
- cout<<"$>\\";
- cin>>ch;
- }
- }while(ch=='y'||ch=='Y');
不断重复出现在几个成员函数中.这样的重复编写,表明对于OOP抽象的能力还有待提高.
- 细节问题应多多关注虽然在程序的编写中,已经有意识的去设置一部分的限定条件,防止用户交互时的错误导致程序崩溃的问题发生,比如引入提示信息,或者加入容错语句,类似于” while(ch=='y'||ch=='Y')”这种预判用户输入的情况.但部分问题还是没有考虑周全.比如在C语言中经常使用的char字符类型,在C++中被要求用string类型代替,但是在输入密码的部分,最终结果出现了明码显示的部分: 这在实际的使用过程中是应该有所避免的,是程序可以继续改进的方面;
- 熟练度有待提高虽然在最终程序可以成功运行,但是在代码编写的过程中,还是遇到了大大小小的许多问题,比如cin,cout输入输出流的应用,成员函数的函数头,作用域,以及构造函数的写法等等.而大部分的错误,都是编译器能够检查出来的基础”语法错误”;这表明当前的练习还远远不够,对于基础知识的熟练度仍有待加强.
总体上说,这次的ATM机实现的问题并不是一个难度很大的问题,其中所需要的核心算法并不是十分复杂,重点还是放在了语法,句法和OOP的思维能力训练上.这次实验发现出的问题,应作为自己在下一步在学习C++知识方面的重点.
附:程序源代码:
- #include<iostream>
- #include<cstring>
- #include<cstdlib>
- #include<Windows.h>
- using namespace std;
- class consumer;
- class ATM{public:
- ATM(consumer & cn):cnsm(cn){}
- void welcome(); //欢迎界面
- bool check_passwd(string num,string pwd); //核对密码
- void change_passwd(); //修改密码
- void fetchmoney(); //取款
- void deposit(); //存款
- void information(); //查询信息
- void exitATM(); //退出系统
- void functionshow(); //功能界面
- void transfer(); //转账
- void lock(); //锁机private:
- int times; //记录密码输入次数
- consumer &cnsm;};
- class consumer //用户{public:
- friend class ATM;
- consumer(string Name,string Kahao,float Money,string Password);protected:
- string get_name(); //取得姓名
- string get_kahao(); //取得卡号
- string get_passwd(); //取得密码
- float get_money(); //取得余额
- void set_passwd(string pwd); //设置密码
- void set_money(int sign,float m); //关于money的存/取款操作
- private:
- string passwd; //用户密码
- string name; //用户姓名
- string kahao; //用户卡号
- float money; //用户余额};
- consumer::consumer(string Name,string Kahao,float Money,string Password) //构造函数,建立账户{
- name=Name;
- kahao=Kahao;
- money=Money;
- passwd=Password;}
- float consumer::get_money() //取得余额{
- return money;}
- string consumer::get_name() //取得姓名{
- return name;}
- string consumer::get_kahao() //取得卡号{
- return kahao;}
- string consumer::get_passwd() //取得密码{
- return passwd;}
- void consumer::set_passwd(string pwd)//设置密码{
- passwd=pwd;}
- void ATM::welcome() //登录界面{
- times=0;
- cout<<"*欢迎使用银行ATM自动取款机*"<<endl;
- string pwd,num,ch;
- do
- {
- cout<<endl<<"请输入卡号:";
- cin>>num;
- cout<<"请输入密码:";
- cin>>pwd;
- if(!check_passwd(num,pwd))
- {
- cout<<"你输入的卡号或密码有误,请重新输入"<<endl;
- times++;
- }
- else
- {
- functionshow();
- }
- }while(times<3);
- lock();}
- bool ATM::check_passwd(string num,string pwd){
- if(num==cnsm.get_kahao()&& pwd==cnsm.get_passwd())
- return true;
- else
- return false;}
- void ATM::functionshow(){
- int n;
- do
- {
- cout <<endl<<"请输入相应的操作序号进行操作: "<<endl;
- cout<<"1)修改密码 "<<endl
- <<"2)取款 "<<endl
- <<"3)查询余额 "<<endl
- <<"4)转账 "<<endl
- <<"5)存款 "<<endl
- <<"6)退出系统 "<<endl;
- cout<<"$>\\";
- cin>>n;
- while(n<1||n>6)
- {
- cout<<"请输入正确的操作序号!"<<endl;
- cout<<"$>\\";
- cin>>n;
- }
- switch(n)
- {
- case 1: change_passwd();
- break;
- case 2: fetchmoney();
- break;
- case 3: information();
- break;
- case 4: transfer();
- break;
- case 5: deposit();
- break;
- case 6: exitATM();
- break;
- }
- }while(true);}
- void ATM::change_passwd(){
- string pwd,repwd;
- times=0;
- do
- {
- cout<<endl<<"请输入旧密码:";
- cin>>pwd;
- if(!check_passwd(cnsm.get_kahao(),pwd))
- {
- times++;
- cout<<"密码输入错误!"<<endl;
- }
- else
- break;
- }while(times<3);
- if(times==3)
- lock();
- int k=0;
- int t=0;
- do
- {
- k=0;
- cout<<"请输入新密码:";
- cin>>pwd;
- int g=0;
- int v=0;
- g=pwd.length();
- if(g<6)
- {
- k=1;
- cout<<"密码不能小于6位"<<endl;
- }
- if(g>6)
- {
- cout<<"请再输入一次新密码:";
- cin>>repwd;
- if(pwd!=repwd)
- {
- cout<<"你输入的两次密码不一样,请重新输入!"<<endl;
- }
- }
- }while(t!=0||k==1);
- cnsm.set_passwd(pwd);
- cout<<"密码修改成功,请牢记!"<<endl;}
- void ATM::fetchmoney( ){
- int m;
- char ch;
- do
- {
- cout<<endl<<"请输入取款金额:(1.每次最多操作5000元;2.取款金额为100的倍数)"<<"\n$>\\";
- cin>>m;
- while(m<=0)
- {
- cout<<"请输入正确的数字!"<<endl;
- cout<<"$>\\";
- cin>>m;
- }
- if(m>5000)
- {
- cout<<"对不起,每次操作最多5000元"<<endl;
- }
- else
- {
- if((int)m%100!=0)
- {
- cout<<"对不起,取款金额为100的倍数"<<endl;
- }
- else
- {
- if(cnsm.get_money()-m<0)
- {
- cout<<"对不起,余额不足!"<<endl;
- }
- else
- {
- cout<< endl<<"操作成功!" <<endl;
- int sign = 0;
- cnsm.set_money(sign,m);
- }
- }
- }
- cout<<"是否要继续此操作:(Y/N)"<<endl;
- cout<<"$>\\";
- cin>>ch;
- while(ch!='n'&&ch!='Y'&&ch!='y')
- {
- cout<<"$>\\";
- cin>>ch;
- }
- }while(ch=='y'||ch=='Y');}
- void ATM::information()//信息页面{
- cout<<"**************************"<<endl;
- cout<<"*"<<endl;
- cout<<"* 用户姓名:"<<cnsm.get_name()<<endl;
- cout<<"* 卡号: "<<cnsm.get_kahao()<<endl;
- cout<<"* 余额: "<<cnsm.get_money()<<endl;
- cout<<"**************************"<<endl;}
- void ATM::transfer(){
- int m;
- unsigned int c;
- char ch;
- do
- {
- cout<<"请输入对方账号: "<<endl;
- cout<<"$>\\";
- cin>>c;
- cout<<endl<<"请输入转账金额:(为保证安全,每次最多操作5000元)"<<"\n$>\\";
- cin>>m;
- while(m<=0)
- {
- cout<<"请输入正确的数字!"<<endl;
- cout<<"$>\\";
- cin>>m;
- }
- if(m>5000)
- {
- cout<<"对不起,每次5000元"<<endl;
- }
- else
- {
- if(cnsm.get_money()-m<0)
- {
- cout<<"对不起,余额不足!"<<endl;
- }
- else
- {
- cout<< endl<<"操作成功!" <<endl;
- int sign = 0;
- cnsm.set_money(sign,m);
- }
- }
- cout<<"是否要继续此操作:(Y/N)"<<endl;
- cout<<"$>\\";
- cin>>ch;
- while(ch!='n'&&ch!='Y'&&ch!='y')
- {
- cout<<"$>\\";
- cin>>ch;
- }
- }while(ch=='y'||ch=='Y');}void ATM::deposit(){
- int m;
- char ch;
- do
- {
- cout<<endl<<"请输入存款金额:(1.每次最多操作5000元;2.存款金额为100的倍数)"<<"\n$>\\";
- cin>>m;
- while(m<=0)
- {
- cout<<"请输入正确的数字!"<<endl;
- cout<<"$>\\";
- cin>>m;
- }
- if(m>5000)
- {
- cout<<"对不起,每次5000元"<<endl;
- }
- else
- {
- if((int)m%100!=0)
- {
- cout<<"对不起,存款金额为100的倍数"<<endl;
- }
- else
- {
- cout<< endl<<"操作成功!" <<endl;
- int sign = 1;
- cnsm.set_money(sign,m);
- }
- }
- cout<<"是否要继续此操作:(Y/N)"<<endl;
- cout<<"$>\\";
- cin>>ch;
- while(ch!='n'&&ch!='Y'&&ch!='y')
- {
- cout<<"$>\\";
- cin>>ch;
- }
- }while(ch=='y'||ch=='Y');}void ATM::lock(){
- cout<<endl<<"您的错误次数过多!"<<endl;
- cout<<endl<<"感谢您的使用,请取回您的卡片,欢迎下次光临!"<<endl;
- cout<<""<<endl;
- exit(0);
- }
- void ATM::exitATM(){
- cout<<"成功退出系统!谢谢!"<<endl;
- exit(0);}
- void consumer::set_money (int sign,float m){
- if(sign) //sign==0代表取款操作
- money=money-m;
- else //否则存款
- money=money+m;}
- int main(){
- SetConsoleTitle("ATM自助柜员机@孙嘉成");
- consumer c1("孙嘉成","123456",10000.00F,"666888");//构造一个用户
- ATM atm(c1);
- atm.welcome();
- return 0;
- }