[啸作业]ATM模拟程序的设计与实现

前言

文章灵感源自于好兄弟的求助。好兄弟让我写一个 ATM 模拟程序来和他的对比一下。

从 OI 层面来看,这不就是纯纯的中等模拟吗?直接启洞!

设计

分析

我们先来看看要求:

ATM模拟程序能够完成ATM的主要功能,包括:
①显示欢迎词及提示信息;
②用户插卡,ATM验证用户账号及密码有效性,输入错误3次即被锁卡;
③余额查询:初始余额为10000元;
④取款功能:每次取款余额为100的整数倍,有单笔和单日金额限制;
⑤转账功能:可将本账户中的存款转入其它账户,转入账户账号需两次输入确认;
⑥修改密码:密码为6位数字,新密码需要两次输入确认;
⑦退卡。
设计实现命令行界面,界面应友好、方便操作。

不着急分析要求,我们再看看 ATM 机的工作流程:

插卡(进入系统)-> 登录 -> 用户操作(存取款等) ->退卡

通过分析了工作流程,我们可以发现一个简单的 ATM 机可以分为三个子系统:主界面系统、登录系统、用户端操作系统。

再回头看看设计要求,我们可以发现要求 ① 是贯穿 3 个子系统的,要求 ② 则是对于登陆系统来说的,剩下的要求都是对用户操作系统的要求,知道了这些,我们就可以开始设计程序了。

总体设计思路:使用类来实现 ATM 机的模拟。

代码

账户

首先先建立账户信息。一个账户所包含的信息有:用户名、卡号、密码、身份证号、余额、银行卡状态以及银行卡限额(和现实相似,I 类卡和 II 类卡)

使用结构体来定义这些内容,代码如下:

struct Account{
	string cardid;
	string user_name;
	string idcard;
	string password;
	double money;
	bool lock;
	int limit;
};

卡号,身份证号,用户名可能长达十几位,因此使用 string 来存储。
密码固定六位,方便判断也用了 string 。(用 int 其实也可以)

钱可能会出现小数,所以我们使用 double 类型。

lock 表示银行卡状态。0为未锁卡,1为锁卡。

limit 表示限额。

主界面

我们首先使用 类 来定义 ATM 系统

class ATMsystem {
public:
	vector<Account> accountlist; //银行账户存储,方便查找
	const int once_limit = 1e9+7; //一次的限额,为了方便就这样定义了
}atm;

接下来是写主界面系统,我们命名为 sys (防止和system函数重名)

主界面比较容易,就是一个按钮对应一个操作,一个操作对应一个函数。

void sys(){
		while(1) {
			clear();
			cout<<"=============== ATM 系统 ==============="<<endl;
			cout<<"欢迎使用 ATM 机!请选择你要操作的类型"<<endl;
			cout<<"1、银行开户\n2、用户登录\n3、退出系统"<<endl;
			cout<<"按5可获取帮助"<<endl;
			int op;
			while( 1 ) {
				cin >> op;
				if( op == 0 ) op = 3;
				if(op == 1 || op == 2 || op == 3 || op == 4 || op == 5 ) break;
				cout << "操作错误!请重新输入" << endl;
			}
			if(op==1) {
				clear();
				add();
			}
			else if(op==2) {
				int record = login();
				//if( record != -1 ) { cout<<record<<"\n";system("pause");/*cout<<accountlist[record].money<<'\n';*/}
				if( record != -1 ) user_command( accountlist[record] );
			}
			else if( op == 3 ) {
				close();
				break;
			}
			else if( op == 4 ) {clear();checklist();system("pause");}
			else if( op == 5 ) {help();}
		}
	}

创建账户

如果用户选择了1(银行开户),就跳转到创建账户函数(命名为 add 或者 registered 均可),这里命名为 add。

创建账户需要经历以下过程:

输入姓名 -> 输入身份证号 -> 输入密码 -> 二次确认 -> 随机一个银行卡号,完成账户创建。

其中:身份证号、密码需要验证是否合法。身份证号为 18 位,密码为 6 位。

void add() {
		Account user;

		cout << "请输入姓名:" << endl;
		cin>>user.user_name;

		cout << "请输入身份证号:" << endl;
		while(1) {
			cin >> user.idcard;
			if( user.idcard == "0" ) return ;
			if( user.idcard.size()==18 ) break;
			else cout<< "格式错误!请重新输入。"<< endl;			
		}

		cout << "请输入密码" << endl;
		while(1) {
			cin >> user.password;
			while( user.password.size() != 6 ) {cout << "格式错误!请重新输入" << endl; cin >> user.password;}
			if ( check_password( user.password ) == 1 ) {
				cout << "请再次确认密码!" <<endl;
				string temp;
				cin >> temp;
				while( temp.size() != 6 ) {cout << "格式错误!请重新输入" << endl; cin >> temp;}
				if( temp == user.password ) {
					user.money = 10000 ; user.lock = 0; user.limit = 1000000;
					user.cardid = id_rand();
					accountlist.push_back(user);
					cout << "创建账户成功!您的账户是: " << user.cardid << endl;
					break;
				}
			}
		}
		cout<<accountlist.size()<<'\n';
		system("pause");//暂停,方便用户记录卡号。
	}

登录

如果用户选择了 2 (登录),跳转至登录系统。这里将登录系统命名为 login。

login 函数应为 int 型,以便确认是否能够登录以及返回登录账户在 accountlist 的位置。

登录系统流程:

插卡(输入卡号) -> 输入密码 -> 进入操作系统/返回主界面

这里需要注意以下几点:

  • 密码输错三次马上锁卡,告知用户并返回主界面;
  • 检查密码位数是否合法,不合法的密码不能算输错密码;
  • 如果卡已经被上锁,告知用户并退回主界面;
  • 成功登录,返回账户返回登录账户在 accountlist 的位置,否则返回 -1。(因为 vector 数组从 0 开始)
int login() {
		clear();
		int cnt = 0,flag; Account user;
		cout << "请输入账户" << endl;
		while(1) {
			flag = -1; string str;
			cin >> str;
			if( str == "0" ) return -1;
			for(int i=0;i<(int)accountlist.size();++i) {
				if( accountlist[i].cardid == str ) {
					user = accountlist[i];
					flag = i;
					break;
				}
			}
			if( flag != -1 ) break;
			else cout << "该账户不存在!请重新输入" << endl;
		}
		if( user.lock == 1 ) {
			cout << "该银行卡以上锁,请联系银行" << endl;
			return -1;
		}
		cout << "请输入密码" << endl;
		while( cnt<3 ) {
			string str;
			cin >> str;
			while(  check_password(str) != 1 ) {
				cout << "密码不合法,请重新输入" << endl;
				cin >> str;
			}
			if( user.password == str ) {
				cout << "登录成功!正在进入操作系统" << endl;
				return flag;
			}
			cnt++;
			cout << "密码错误!还有" << 3-cnt << "次机会" << endl;
		}
		
		if( cnt == 3 ) {
			accountlist[flag].lock = 1;
			cout << "银行卡已上锁,请联系银行!" << endl;
		}
		
		return -1;
}

用户操作系统

成功登录,进入用户操作系统。这里命名为 user_command。

用户操作系统有以下功能:

  1. 存款(额外开发功能,作业内并未要求);
  2. 取款:需要注意取出的钱只能是 100 的整数倍;
  3. 转账:转账可以转到小数点后两位,目标账户必须在本银行中;
  4. 余额查询:返回账户内余额就可以了;
  5. 修改密码:这个简单,输入一次旧密码,一次新密码,二次确认即可;
  6. 退卡:退出 user_command 函数。

需要注意的是,我们需要对 accountlist 内的数据进行修改而不是它的副本(因为最后退出系统保存数据时保存的是 accountlist 内的数据)。这就是为什么 login 函数我们返回的是对应账户在 accountlist 的位置而不是简单的 0-1 的原因。


void user_command(Account &user) {
			while(1) {
				clear();
				cout << "请选择您需要办理的业务" << endl;
				cout << "1、存款" << "\n" << "2、取款" << "\n" << "3、转账" << "\n" ;
				cout << "4、余额查询" << "\n" << "5、修改密码" << "\n" << "6、退卡" << endl;
				int op ;
				cin >> op;
				while( op<1 || op>6 ) {cout << "操作错误!请重新输入" << endl; cin >> op;}
				if( op == 1 ) {
					cout << "本机暂不支持存款业务!" << endl;
				}
				else if( op == 2 ) {
					clear();
					double number = 0 ;int input ;
					cout << "请选择取款金额" << endl;
					cout << "1 - 100" << "\n" << "2 - 200" << "\n" << "3 - 500" << "\n" ;
					cout << "4 - 1000" << "\n" << "5 - 自定义" << endl;
					while( 1 ) {
						cin >> input;
						if( input < 1 || input > 5 ) continue;  //need fix
						break;
					}
					if( input == 1 ) number = 100;
					else if( input == 2 ) number = 200;
					else if( input == 3 ) number = 500;
					else if( input == 4 ) number = 1000;
					else if( input == 5 ) {
						cout << "请输入金额" << endl;
						int temp = 0;
						cin >> temp ;
						while( temp % 100 != 0 ) {
							cout << "金额错误!请重新输入" << endl;
							cin >> temp ;
						}
						number = temp * 1.0 ;
					}
					/*cout<<number<<" "<<user.limit<<'\n';
					system("Pause");*/
					if( user.money < number ) { cout << "余额不足!" << endl; system("pause"); continue ;}
					else if( number > user.limit ) { cout << "无法取出,因为今日可取款数量仅剩" << user.limit <<"元,如有需要请到柜台办理。" << endl; system("pause"); continue;}
					else if( number > once_limit ) { cout << "操作失败!单笔仅可取出 " << once_limit << "元,如有需要请到柜台办理。" << endl; system("pause"); continue;}
					user.money-=number; user.limit-=number;
					cout << "操作成功!账户余额还剩" << user.money << endl;
				}
				else if( op == 3 ) {
					string id;  Account target; double number; int flag = -1;
					clear();
					cout << "请输入目标账户的卡号" << endl;
					while(1) {
						cin >> id;
						flag = -1;
						for(int i=0;i<(int)accountlist.size();++i) {
							if( accountlist[i].cardid == id ) {
								target = accountlist[i];
								flag = i;
								break;
							}
						}
						if( flag != -1 ) break;
						else cout << "目标账户不存在,请重新输入!" << endl;
					}
					cout << "请输入转账金额" << endl;
					cin >> number;
					//cout << number << " " << user.money << endl;
					while( number > user.money ) {
						if( number == 0 ) break;
						cout << "余额不足!" << endl;
						Sleep(5000);
						cin >> number;
					}
					if( number == 0 ) continue;
					cout << "请再次确认目标账户的卡号" << endl;
					cin >> id;
					while( id!=target.cardid ) {
						clear();
						cout << "两次输入账户不一致,请重新输入" << endl;
						cin >> id;
					}
					user.money-=number; accountlist[flag].money+=number;
					cout << "操作成功!已向目标账户转账" << number << "元" << endl;
				}
				else if( op == 4 ) {
					clear();
					cout << "您的账户目前余额为: " << user.money << "元" << endl;
				}
				else if( op == 5 ) {
					string old_password,new_password,str;
					cout << "请输入旧密码" << endl;
					while(1) {
						cin>>old_password;
						if( old_password != user.password ) {
							cout << "密码错误,请重新输入!" << endl;
							continue;
						}
						else break;
					}
					cout << "请输入新密码" << endl;
					cin >> new_password;
					while( old_password == new_password ) {
						cout << "新密码不能与旧密码相同!请重新输入" << endl;
						cin >> new_password;
					}
					cout << "请再次确认新密码:" << endl;
					cin >> str;
					while( str != new_password ) {
						cout << "两次输入不一致!请重新输入" << endl;
						cin >> str;
					}
					user.password = new_password;
					cout << "修改成功!" << endl;
				}
				else if( op == 6 ) {
					clear();
					cout << "退卡成功!" << endl;
					system("pause");
					break;
				}
				system("pause");
			}
			return ;
		}

至此,我们三大子系统已经全部实现。

接下来是一些三大子系统所需的小功能:

  • 随机卡号
string id_rand() {
		srand(time(0));
		string temp="";
		for(int i=1;i<=19;++i) {
			int num = rand() % 10;
			char x = num + '0';
			temp.push_back(x);
		}
		return temp;
	}
  • 密码合法性检查
bool check_password(string password) {
		if( password.size()<6 ) return false;
		for(int i=0;i<6;++i) {
			if( password[i]<'0' || password[i]>'9' ) return false;
		}
		return true;
	}
  • clear函数

清除屏幕内容,保持交互界面干净整洁

  • 数据文件读写
    略。

总代码

#include<iostream>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<string>
#include<windows.h>
using namespace std;
const int inf = 2147483647;
const double eps = 1e-3;

struct Account{
	string cardid;
	string user_name;
	string idcard;
	string password;
	double money;
	bool lock;
	int limit;
};

class ATMsystem {
	public:
		vector<Account> accountlist; const int once_limit = 1e9+7;
	public:
		bool check_password(string password) {
			if( password.size()<6 ) return false;
			for(int i=0;i<6;++i) {
				if( password[i]<'0' || password[i]>'9' ) return false;
			}
			return true;
		}

		string id_rand() {
			srand(time(0));
			string temp="";
			for(int i=1;i<=19;++i) {
				int num = rand() % 10;
				char x = num + '0';
				temp.push_back(x);
			}
			return temp;
		}

		void init() {
			ifstream fin;
			fin.open("data.txt",ios::in);
			if( !fin.is_open() ) {
				cout << "读取文件失败!" << endl;
				return ;
			}
			char line1[1024]={0},line2[1024]={0}; Account registered;
			while(fin.getline(line1,sizeof(line1))) {
				Account temp;
				stringstream word(line1);
				word >> temp.cardid;
				word >> temp.user_name;
				word >> temp.idcard;
				word >> temp.password;
				fin.getline(line2,sizeof(line2));
				istringstream string_to_num(line2);
				string_to_num >> temp.money >> temp.lock >> temp.limit;
				accountlist.push_back(temp);
			}
			fin.close();
		}
		
		void close() {
			ofstream fout;
			fout.open("data.txt",ios::out);
			if( !fout.is_open() ) {
				cout << "写入文件失败!" << endl;
				return ;
			}
			for(int i=0;i<(int)accountlist.size();++i) {
				fout << accountlist[i].cardid << " " << accountlist[i].user_name << " ";
				fout << accountlist[i].idcard << " " << accountlist[i].password << endl ;
				fout << accountlist[i].money << " " << accountlist[i].lock << " " << accountlist[i].limit << endl;
			}
			fout.close();
		}

		void Administrator() {
			Account admin;
			admin.cardid="001"; admin.user_name="admin"; admin.idcard="001"; admin.password="123456";
			admin.money=10000; admin.lock=0; admin.limit = inf;
			accountlist.push_back(admin);
			return ;
		}

		void checklist() {
			cout<<accountlist.size()<<"\n";
			for(int i=0;i<(int)accountlist.size();++i) {
				cout<<accountlist[i].cardid<<" "<<accountlist[i].user_name<<" "<<accountlist[i].password;
				cout<<" "<<accountlist[i].money<<'\n';
			}
		}

		void clear() {
			system("cls");
			return ;
		}

		void help() {
			clear();
			cout << "按 0 可以退回上一个界面" << endl;
			system("pause");
		}

		void add() {
			Account user;

			cout << "请输入姓名:" << endl;
			cin>>user.user_name;

			cout << "请输入身份证号:" << endl;
			while(1) {
				cin >> user.idcard;
				if( user.idcard == "0" ) return ;
				if( user.idcard.size()==18 ) break;
				else cout<< "格式错误!请重新输入。"<< endl;
			}

			cout << "请输入密码" << endl;
			while(1) {
				cin >> user.password;
				while( user.password.size() != 6 ) {cout << "格式错误!请重新输入" << endl; cin >> user.password;}
				if ( check_password( user.password ) == 1 ) {
					cout << "请再次确认密码!" <<endl;
					string temp;
					cin >> temp;
					while( temp.size() != 6 ) {cout << "格式错误!请重新输入" << endl; cin >> temp;}
					if( temp == user.password ) {
						user.money = 10000 ; user.lock = 0; user.limit = 1000000;
						user.cardid = id_rand();
						accountlist.push_back(user);
						cout << "创建账户成功!您的账户是: " << user.cardid << endl;
						break;
					}
				}
			}
			cout<<accountlist.size()<<'\n';
			system("pause");
		}

		int login() {
			clear();
			int cnt = 0,flag; Account user;
			cout << "请输入账户" << endl;
			while(1) {
				flag = -1; string str;
				cin >> str;
				if( str == "0" ) return -1;
				for(int i=0;i<(int)accountlist.size();++i) {
					if( accountlist[i].cardid == str ) {
						user = accountlist[i];
						flag = i;
						break;
					}
				}
				if( flag != -1 ) break;
				else cout << "该账户不存在!请重新输入" << endl;
			}
			if( user.lock == 1 ) {
				cout << "该银行卡以上锁,请联系银行" << endl;
				return -1;
			}
			cout << "请输入密码" << endl;
			while( cnt<3 ) {
				string str;
				cin >> str;
				while(  check_password(str) != 1 ) {
					cout << "密码不合法,请重新输入" << endl;
					cin >> str;
				}
				if( user.password == str ) {
					cout << "登录成功!正在进入操作系统" << endl;
					return flag;
				}
				cnt++;
				cout << "密码错误!还有" << 3-cnt << "次机会" << endl;
			}
			
			if( cnt == 3 ) {
				accountlist[flag].lock = 1;
				cout << "银行卡已上锁,请联系银行!" << endl;
			}
			
			return -1;
		}

		void user_command(Account &user) {
			while(1) {
				clear();
				cout << "请选择您需要办理的业务" << endl;
				cout << "1、存款" << "\n" << "2、取款" << "\n" << "3、转账" << "\n" ;
				cout << "4、余额查询" << "\n" << "5、修改密码" << "\n" << "6、退卡" << endl;
				int op ;
				cin >> op;
				while( op<1 || op>6 ) {cout << "操作错误!请重新输入" << endl; cin >> op;}
				if( op == 1 ) {
					cout << "本机暂不支持存款业务!" << endl;
				}
				else if( op == 2 ) {
					clear();
					double number = 0 ;int input ;
					cout << "请选择取款金额" << endl;
					cout << "1 - 100" << "\n" << "2 - 200" << "\n" << "3 - 500" << "\n" ;
					cout << "4 - 1000" << "\n" << "5 - 自定义" << endl;
					while( 1 ) {
						cin >> input;
						if( input < 1 || input > 5 ) continue;  //need fix
						break;
					}
					if( input == 1 ) number = 100;
					else if( input == 2 ) number = 200;
					else if( input == 3 ) number = 500;
					else if( input == 4 ) number = 1000;
					else if( input == 5 ) {
						cout << "请输入金额" << endl;
						int temp = 0;
						cin >> temp ;
						while( temp % 100 != 0 ) {
							cout << "金额错误!请重新输入" << endl;
							cin >> temp ;
						}
						number = temp * 1.0 ;
					}
					/*cout<<number<<" "<<user.limit<<'\n';
					system("Pause");*/
					if( user.money < number ) { cout << "余额不足!" << endl; system("pause"); continue ;}
					else if( number > user.limit ) { cout << "无法取出,因为今日可取款数量仅剩" << user.limit <<"元,如有需要请到柜台办理。" << endl; system("pause"); continue;}
					else if( number > once_limit ) { cout << "操作失败!单笔仅可取出 " << once_limit << "元,如有需要请到柜台办理。" << endl; system("pause"); continue;}
					user.money-=number; user.limit-=number;
					cout << "操作成功!账户余额还剩" << user.money << endl;
				}
				else if( op == 3 ) {
					string id;  Account target; double number; int flag = -1;
					clear();
					cout << "请输入目标账户的卡号" << endl;
					while(1) {
						cin >> id;
						flag = -1;
						for(int i=0;i<(int)accountlist.size();++i) {
							if( accountlist[i].cardid == id ) {
								target = accountlist[i];
								flag = i;
								break;
							}
						}
						if( flag != -1 ) break;
						else cout << "目标账户不存在,请重新输入!" << endl;
					}
					cout << "请输入转账金额" << endl;
					cin >> number;
					//cout << number << " " << user.money << endl;
					while( number > user.money ) {
						if( number == 0 ) break;
						cout << "余额不足!" << endl;
						Sleep(5000);
						cin >> number;
					}
					if( number == 0 ) continue;
					cout << "请再次确认目标账户的卡号" << endl;
					cin >> id;
					while( id!=target.cardid ) {
						clear();
						cout << "两次输入账户不一致,请重新输入" << endl;
						cin >> id;
					}
					user.money-=number; accountlist[flag].money+=number;
					cout << "操作成功!已向目标账户转账" << number << "元" << endl;
				}
				else if( op == 4 ) {
					clear();
					cout << "您的账户目前余额为: " << user.money << "元" << endl;
				}
				else if( op == 5 ) {
					string old_password,new_password,str;
					cout << "请输入旧密码" << endl;
					while(1) {
						cin>>old_password;
						if( old_password != user.password ) {
							cout << "密码错误,请重新输入!" << endl;
							continue;
						}
						else break;
					}
					cout << "请输入新密码" << endl;
					cin >> new_password;
					while( old_password == new_password ) {
						cout << "新密码不能与旧密码相同!请重新输入" << endl;
						cin >> new_password;
					}
					cout << "请再次确认新密码:" << endl;
					cin >> str;
					while( str != new_password ) {
						cout << "两次输入不一致!请重新输入" << endl;
						cin >> str;
					}
					user.password = new_password;
					cout << "修改成功!" << endl;
				}
				else if( op == 6 ) {
					clear();
					cout << "退卡成功!" << endl;
					system("pause");
					break;
				}
				system("pause");
			}
			return ;
		}

		void sys(){
			while(1) {
				clear();
				cout<<"=============== ATM 系统 ==============="<<endl;
				cout<<"欢迎使用 ATM 机!请选择你要操作的类型"<<endl;
				cout<<"1、银行开户\n2、用户登录\n3、退出系统"<<endl;
				cout<<"按5可获取帮助"<<endl;
				int op;
				while( 1 ) {
					cin >> op;
					if( op == 0 ) op = 3;
					if(op == 1 || op == 2 || op == 3 || op == 4 || op == 5 ) break;
					cout << "操作错误!请重新输入" << endl;
				}
				if(op==1) {
					clear();
					add();
				}
				else if(op==2) {
					int record = login();
					//if( record != -1 ) { cout<<record<<"\n";system("pause");/*cout<<accountlist[record].money<<'\n';*/}
					if( record != -1 ) user_command( accountlist[record] );
				}
				else if( op == 3 ) {
					close();
					break;
				}
				else if( op == 4 ) {clear();checklist();system("pause");}
				else if( op == 5 ) {help();}
			}
		}
}atm;

int main() {
	atm.init();
	//atm.Administrator();
	atm.sys();
	return 0;
}

代码已经加入防抄袭,请自己独立完成呐~

总结

OIer 毫不畏惧。不需要过多的思维,无脑写就完了!

可以尝试自己开发一下管理员系统和完善存款功能,更加还原现实生活的 ATM 系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值