一、实验平台
Visual C++ 6.0
二、问题分析
2.1 需求分析
本次实验有如下四条需求:
(1)要求程序界面友好且能对操作是否成功进行判断;
(2)要求输入密码时以星号(***)显示;
(3)要求存取款只能以整百金额进行,并对出现的各种情况进行判断;
(4)要求转账时只能对于已有的五个账号(1234567891234567891……)操作。
根据以上四点需求,至少应有菜单(Menu)、输入密码(GetCode)、判断金额(GetInt)和转账判断(Transfer)四个功能函数。除此以外,现实中的ATM机实质上是用户在和银行交互时的接口,在功能执行时通过“银行卡”获取操作权限并记录操作信息。由此,本次实验中除设计完成ATM机类的设计之外,还应设计完成对于“银行卡”(Card)类的设计。
2.2 对ATM类的功能定义和数据类型分析
功能上,现实中的ATM机可执行存款(Save)、取款(Deposit)、查询余额(Dispaly)、检查密码(Check)等基本功能,还可以对初次使用的银行卡进行激活,则在ATM类中至少需要以上几个功能函数。
此外,现实中的ATM机上有一个读取银行卡信息的接口,此接口可以读取当前用户所持卡的信息,并对其中的部分信息进行更改,还能对信息起到一定程度的保密作用。ATM和当前卡二者间的关系在实质上是ATM机“包含”或者“有”(has)当前银行卡,将此种现实关系映射到在本实验中,即表现为ATM机和当前卡的继承关系。由此,可在ATM机中设置一个私有的(private)数据成员当前卡(TheCard),其为一个卡(Card)类的对象。“读卡”这一操作则可通过赋值进行。
另外,现实中用户对于ATM机的操作,是通过面板上的各类按钮实现的。在程序设计时,则可直接将其简化为输入环节,通过显示界面提示用户进行其他操作。
2.3对账户类(卡类)的功能定义和数据类型分析
现实中的银行卡是用户账户信息的物质载体,由于本实验并不考虑其物理性质,则可将卡等同于账户以简化问题。尽管实际中的卡不需要任何操作功能,可以使用结构体(struct)实现,但实验中设计的程序中需要在保护其中数据的同时对其数据执行操作,选择类(class)更为合适。
值得注意的是,前文中提到的ATM类和卡类的继承关系只针对卡类的特定对象,而且实际上只在特定时刻(即用户登录成功后)此种继承关系才成立,因而在此只对“所有卡”的共性加以分析。同时,由于本实验中存在多个卡的对象,还需要考虑其储存方式和使用方式。
从数据角度考虑,卡类所承载的账户信息仅包含其账号(AccountNum)、密码(Code)、余额(Balance),其中账号的数据类型为字符串(string)类型,而密码和余额都为整型(int)。
在存储结构的选择上,由于使用过程中不可避免地要对卡类的特定对象进行操作,且操作时不能更改其他对象的内容,可选择链表作为卡类对象存储时的数据结构。则还需在卡类中添加对链表操作的功能函数。
三、设计/开发解决方案
3.1程序运行流程图
3.2类定义
对于用户,其账户信息存储在卡当中,所以定义Card 类对其信息进行处理,而卡本身只能进行读写和查找。
class Card
{
public:
Card () ;
Card * Creat () ; //生成链表的函数
Card * Search ( string ) ; //查找函数
void SetCode (string ) ; //设置密码
void Open ( string , string ) ;//设置账户和密码(开户)
int GetBalance () ; //返回余额(只读函数)
void SetNum ( int ) ; //设置密码(只写函数)
void Reset ( int a , string b ) ;//对特定账户写入余额
string GetCode () ; //返回密码(只读函数)
string GetAccount () ; //返回账号(只读函数)
private:
string AccountNum; //账号
string Code; //密码
int Balance; //余额
Card * Next; //指向下一个卡的指针(链表)
};
class ATM
{
public:
ATM ( Card * ) ; //构造函数,执行“读卡”功能
int CheckCode ( string ) ; //检查密码
void Save ( int ) ; //存款
void Deposite ( int ) ; //取款
void Transfer (Card * , int) ; //转账
void Change ( string ) ; //修改密码
bool Check ( string Code ) ; //检查密码
void Display () ; //显示余额
int GetB () ; //返回余额
string GetC () ; //返回密码
private:
Card * users ; //私有数据,指向Card的指针,“接口”
};
四、输出结果
4.1 当密码三次输入错误时
4.2 账户输入错误时
4.3 正常登陆后
4.4 存款(金额正确与不正确)
4.5 取款(金额正确与不正确)
4.6 转账
4.7 修改密码
4.8 查询余额
4.9 退卡
五、程序源码
P.S. 建议输出用正则表达式控制一下,要不会很难看……
#include<iostream>
#include<string>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
using namespace std;
int GetInt () ;
string GetAcc () ;
string GetCode () ;
class Card
{
public:
Card () ;
Card * Creat () ;
Card * Search ( string ) ;
void SetCode (string ) ;
void Open ( string , string ) ;
int GetBalance () ;
void SetNum ( int ) ;
void Reset ( int a , string b ) ;
string GetCode () ;
string GetAccount () ;
private:
string AccountNum;
string Code;
int Balance;
Card * Flag;
Card * Next;
};
Card :: Card ()//生成头结点
{
AccountNum = " 0 " ;
Balance = 0 ;
Code = "0" ;
Next = NULL ;
Flag = NULL ;
}
Card HEAD ;
int Card :: GetBalance ()
{
return Balance ;
}
string Card :: GetCode ()
{
return Code ;
}
string Card :: GetAccount ()
{
return AccountNum ;
}
void Card :: SetNum ( int i )
{
Balance = i ;
}
void Card::Open ( string x , string y )
{
AccountNum = x ;
Code = y ;
Balance = 0 ;
}
Card * Card :: Creat ()//生成新节点
{
Card * temp = new Card ;
if ( temp == NULL )
cout << endl << "内存不足,请重新操作" << endl ;
else
temp -> Next = Next ;
Next = temp ;
return temp ;
}
Card * Card :: Search ( string aim )
{
Card * p = this;
Card * q = p;
while ( p -> Next != NULL