现在的位置: 首页 > 综合 > 正文

银行账户ATM实现代码

2014年09月05日 ⁄ 综合 ⁄ 共 3874字 ⁄ 字号 评论关闭

   学习目标:掌握ATM的代码实现,学习项目设计的层次划分

    学习重点:数据的输入输出,项目层次划分

    学习难点:完善该ATM项目,模拟生产环境

/*
 *Account类是与业务和存储无关的类,应该保持最大程度的稳定性,
 *尽量减少业务方法,所有的方法应该只与类本身有关系
 */
 
/*
 *覆盖无参构造函数,初始化各个属性
 */
account::account(){
 id = -1 ;
 memset( name , 0 , sizeof( name ) );
 memset( pwd , 0 , sizeof(pwd) );
 balance = 0 ;
}
/*
 *重载有参构造函数,根据传入的参数初始化成员属性
 */
account::account( char* name , char* pwd ,double b){
 id = generateId();
 strcpy( this->name , name ) ;
 strcpy( this->pwd , pwd ) ;
 balance = b ;
}
/*
 *存款操作,用于增加存款
 */
void   account::save( double s ){
 balance +=  s ;
}
/*
 *取款操作,形参是密码和金额
 */
void   account::withdraw( char* p, double s){
 /*
  *如果密码不正确,抛出异常,跳出程序
  */
 if( strcmp( p , pwd ) != 0 ){
  throw "invalid password" ;
 }
 /*
  *如果余额不足,抛出异常,跳出程序;至少留有10元的年费
  */
 if( balance < s + 10 ){
  throw "no enough money" ;
 } 
 
 /*
  *如果密码不正确,抛出异常
  */alance -= s ;
}
/*
 *查询操作,形参是密码
 */
double account::query( char* p ){
 /*
  *如果密码不正确,抛出异常,跳出程序
  */
 if( strcmp( p , pwd ) != 0 ){
  throw "invalid password" ;
 }

 return balance ;
}
long account::getId(){
 return id ;
}
/*
 *帐户帐号产生器,这是与业务无关的内部操作,私有类型;
 *为了保证持久性和唯一性,通过文件来保存
 */
long account::generateId(){
 //初始化帐号
 long id = 0 ;
 //以二进制形式打开文件
 ifstream ifs( "id.dat",ios::binary );
 //如果文件不存在,打开会出错。这时候应该创建文件
 if( ifs.fail() ){
  long temp = id + 1 ;
  ofstream ofs( "id.dat",ios::binary);
  ofs.write( (char*)&temp,sizeof(long));
  ofs.close();
  return id ;
 }
 //打开文件成功,则读取文件内容,并将更新后的id写到文件里面
 else{
  ifs.read( (char*)&id,sizeof(long));
  ifs.close();
  long temp = id + 1 ;
  ofstream ofs("id.dat",ios::binary);
  ofs.write((char*)&temp,sizeof(long));
  ofs.close();
  return id ;
   
 }      
}

 

 

/*
 *Biz类是业务类,根据业务内容的不同,该类会变化。
 *该类主要负责收集用户信息,调用Account的相关方法,会根据业务的不同而不同
 */
/*
 *开户操作,收集用户的名字、密码和金额,创建一个账户,
 *写到文件中进行持久保存;并且告诉用户他的帐号
 */
void Biz::create(){
 char name[50]; ;
 char pwd[ 50 ] ;
 double balance ;
 cout<<"enter name >";
 cin.getline( name , sizeof(name) );
 cout<<"enter password>";
 cin.getline( pwd , sizeof(pwd ) ) ;
 cout<<"enter balance >";
 cin>>balance ;
 cin.ignore( 255 , '\n' );
 
 account a( name, pwd , balance );
 DA da ;
 try{
  da.write( a ) ; 
  cout<<"create account ok , id = ";
  cout<<a.getId() << endl;
 }catch(const char* p ){
  cout<< p << endl;
 }
}
/*
 *保存操作,收集用户信息,修改文件内容,更新文件中的用户信息
 *如果出现异常,通知用户
 */
void Biz::save(){
 long id ;
 double sum ;
 cout<<"enter id >";
 cin>>id;
 cout<<"enter sum>";
 cin>>sum ;
 cin.ignore( 255, '\n' );
 
 try{
  DA da ;
  account a = da.read( id ) ;
  a.save( sum ) ;
  da.update( a ) ;
  cout<<"save money ok ." << endl; 
 }catch( const char* p ){
  cout<< p << endl;
 }
}
/*
 *取款操作,收集用户信息,修改文件内容,更新文件中的用户信息
 *如果出现异常,通知用户
 */
void Biz::withdraw(){
 long id ;
 char pwd[ 20 ] ;
 double s ;
 cout<<"enter id >";
 cin>>id ;
 cout<<"enter password >";
 cin.ignore( 255 ,'\n' );
 cin.getline( pwd , sizeof(pwd) );
 cout<<"enter sum >";
 cin>>s ;
 cin.ignore( 255 , '\n' );

 try{
  DA da ;
  account a = da.read( id ) ;
  a.withdraw( pwd , s ) ;
  da.update( a ) ;
  cout<<"withdraw ok "<<endl; 
 }catch( const char* p ){
  cout<< p << endl;
 } 
}
/*
 *查询操作,收集用户信息,返回用户帐户金额
 *如果出现异常,通知用户
 */
void Biz::query(){
 long id ;
 char pwd[ 50 ] ;
 cout<<"enter id >";
 cin>>id ;
 cin.ignore( 255 , '\n' );
 cout<<"enter password >";
 cin.getline( pwd , sizeof( pwd ) ) ;

 try{
  DA da ;
  account a = da.read( id ) ;
  double b = a.query( pwd );
  cout<<"BALANCE:" << b << endl; 
 }catch(const char* p ){
  cout<< p << endl;
 }
}

 

/*
 *DA类负责将业务对象(Account类)进行持久化,业务不需要关注如何存储及如何持久化;
 *为了体现分层的正确性,该类一定不会出现Biz类,降低耦合性,提高可复用性。
 *如果需要更换存储位置,只需要改变这个类,而不用改变业务操作
 */
/*
 *把账户信息从文件读到内存
 */
account DA::read(long id ){
 account a ;
 char name[ 100 ] ;
 getNameById( id , name, sizeof(name) );
 ifstream ifs( name,ios::binary );
 if( ifs.fail() ){
  throw "invalid id " ;
 }
 ifs.read((char*)&a, sizeof( a ) ) ;
 ifs.close();
 return a ;
}
/*
 *把账户信息从内存写到文件中
 */
void DA::write( account& a ){
 char name[ 50 ] ;
 getNameById( a.getId() , name, sizeof(name));
 ofstream ofs( name,
  ios::binary );
 if( ofs.fail() ){
    throw "account already exist" ; 
 }
 ofs.write( (char*)&a , sizeof( a ) ) ;
 ofs.close();
}
/*
 *更新账户信息,把账户信息从内存写到文件,进行覆盖
 *应该还有一个查询的操作
 */
void DA::update( account& a){
 char name[ 50 ];
 getNameById(a.getId(),name,sizeof(name));
 ofstream ofs( name,
      ios::binary );
 if( ofs.fail() ){
  throw "No such account";
 }
 ofs.write( (char*)&a , sizeof( a ) ) ;
 ofs.close();
}
/*
 *辅助函数,根据帐户的id得到文件名称。因为文件名称是根据帐号命名的,很有规律
 */
void DA::getNameById(long id,char* p,int len ){
 char* pf = "data/%d.dat";
 sprintf( p , pf , id ) ;
}

 

参考原文:来自互联网。

抱歉!评论已关闭.