#ifndef __DATE_H__
#define __DATE_H__
class Date {
private:
int year;
int month;
int day;
int totalDays;
public:
Date ( int year, int month, int day) ;
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;
}
} ;
#endif
#include "date.h"
#include <iostream>
#include <cstdlib>
using namespace std;
namespace {
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 ( ) ) {
cout << "Invalid date: " ;
show ( ) ;
cout << endl;
exit ( 1 ) ;
}
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 ;
else
return DAYS_BEFORE_MONTH[ month] - DAYS_BEFORE_MONTH[ month - 1 ] ;
}
void Date: : show ( ) const {
cout << getYear ( ) << "-" << getMonth ( ) << "-" << getDay ( ) ;
}
#ifndef ARRAY_H
#define ARRAY_H
#include <cassert>
template < class T>
class Array {
private:
T* list;
int size;
public:
Array ( int sz = 50 ) ;
Array ( const Array< T> & a) ;
~ Array ( ) ;
Array< T> & operator = ( const Array< T> & rhs) ;
T & operator [ ] ( int i) ;
const T & operator [ ] ( int i) const ;
operator T * ( ) ;
operator const T * ( ) const ;
int getSize ( ) const ;
void resize ( int sz) ;
} ;
template < class T>
Array< T> : : Array ( int sz) {
assert ( sz >= 0 ) ;
size = sz;
list = new T [ size] ;
}
template < class T>
Array< T> : : ~ Array ( ) {
delete [ ] list;
}
template < class T>
Array< T> : : Array ( const Array< T> & a) {
size = a. size;
list = new T[ size] ;
for ( int i = 0 ; i < size; i++ )
list[ i] = a. list[ i] ;
}
template < class T>
Array< T> & Array< T> : : operator = ( const Array< T> & rhs) {
if ( & rhs != this) {
if ( size != rhs. size) {
delete [ ] list;
size = rhs. size;
list = new T[ size] ;
}
for ( int i = 0 ; i < size; i++ )
list[ i] = rhs. list[ i] ;
}
return * this;
}
template < class T>
T & Array< T> : : operator[ ] ( int n) {
assert ( n >= 0 && n < size) ;
return list[ n] ;
}
template < class T>
const T & Array< T> : : operator[ ] ( int n) const {
assert ( n >= 0 && n < size) ;
return list[ n] ;
}
template < class T>
Array< T> : : operator T * ( ) {
return list;
}
template < class T>
Array< T> : : operator const T * ( ) const {
return list;
}
template < class T>
int Array< T> : : getSize ( ) const {
return size;
}
template < class T>
void Array< T> : : resize ( int sz) {
assert ( sz >= 0 ) ;
if ( sz == size)
return ;
T* newList = new T [ sz] ;
int n = ( sz < size) ? sz : size;
for ( int i = 0 ; i < n; i++ )
newList[ i] = list[ i] ;
delete[ ] list;
list = newList;
size = sz;
}
#endif
#ifndef __ACCUMULATOR_H__
#define __ACCUMULATOR_H__
#include "date.h"
class Accumulator {
private:
Date lastDate;
double value;
double sum;
public:
Accumulator ( const Date & date, double value)
: lastDate ( date) , value ( value) , sum ( 0 ) { }
double getSum ( const Date & date) const {
return sum + value * ( date - lastDate) ;
}
void change ( const Date & date, double value) {
sum = getSum ( date) ;
lastDate = date;
this-> value = value;
}
void reset ( const Date & date, double value) {
lastDate = date;
this-> value = value;
sum = 0 ;
}
} ;
#endif
#ifndef __ACCOUNT_H__
#define __ACCOUNT_H__
#include "date.h"
#include "accumulator.h"
#include <string>
class Account {
private:
std: : string id;
double balance;
static double total;
protected:
Account ( const Date & date, const std: : string & id) ;
void record ( const Date & date, double amount, const std: : string & desc) ;
void error ( const std: : string & msg) const ;
public:
const std: : string & getId ( ) const { return id; }
double getBalance ( ) const { return balance; }
static double getTotal ( ) { return total; }
virtual void deposit ( const Date & date, double amount, const std: : string & desc) = 0 ;
virtual void withdraw ( const Date & date, double amount, const std: : string & desc) = 0 ;
virtual void settle ( const Date & date) = 0 ;
virtual void show ( ) const ;
} ;
class SavingsAccount : public Account {
private:
Accumulator acc;
double rate;
public:
SavingsAccount ( const Date & date, const std: : string & id, double rate) ;
double getRate ( ) const { return rate; }
virtual void deposit ( const Date & date, double amount, const std: : string & desc) ;
virtual void withdraw ( const Date & date, double amount, const std: : string & desc) ;
virtual void settle ( const Date & date) ;
} ;
class CreditAccount : public Account {
private:
Accumulator acc;
double credit;
double rate;
double fee;
double getDebt ( ) const {
double balance = getBalance ( ) ;
return ( balance < 0 ? balance : 0 ) ;
}
public:
CreditAccount ( const Date & date, const std: : 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 ( ) ;
else
return credit;
}
virtual void deposit ( const Date & date, double amount, const std: : string & desc) ;
virtual void withdraw ( const Date & date, double amount, const std: : string & desc) ;
virtual void settle ( const Date & date) ;
virtual void show ( ) const ;
} ;
#endif
#include "account.h"
#include <cmath>
#include <iostream>
using namespace std;
double Account: : total = 0 ;
Account: : Account ( const Date & date, const string & id)
: id ( id) , balance ( 0 ) {
date. show ( ) ;
cout << "\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 ( ) const {
cout << id << "\tBalance: " << balance;
}
void Account: : error ( const string & msg) const {
cout << "Error(#" << id << "): " << msg << endl;
}
SavingsAccount: : SavingsAccount ( const Date & date, const string & id, double rate)
: Account ( date, id) , rate ( rate) , acc ( date, 0 ) { }
void SavingsAccount: : deposit ( const Date & date, double amount, const string & desc) {
record ( date, amount, desc) ;
acc. change ( date, getBalance ( ) ) ;
}
void SavingsAccount: : 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 SavingsAccount: : settle ( const Date & date) {
if ( date. getMonth ( ) == 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 ( ) ) ;
}
}
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 ( ) const {
Account: : show ( ) ;
cout << "\tAvailable credit:" << getAvailableCredit ( ) ;
}
#include "account.h"
#include "Array.h"
#include <iostream>
using namespace std;
int main ( ) {
Date date ( 2008 , 11 , 1 ) ;
Array< Account * > accounts ( 0 ) ;
cout << "(a)add account (d)deposit (w)withdraw (s)show (c)change day (n)next month (e)exit" << endl;
char cmd;
do {
date. show ( ) ;
cout << "\tTotal: " << Account: : getTotal ( ) << "\tcommand> " ;
char type;
int index, day;
double amount, credit, rate, fee;
string id, desc;
Account* account;
cin >> cmd;
switch ( cmd) {
case 'a' :
cin >> type >> id;
if ( type == 's' ) {
cin >> rate;
account = new SavingsAccount ( date, id, rate) ;
} else {
cin >> credit >> rate >> fee;
account = new CreditAccount ( date, id, credit, rate, fee) ;
}
accounts. resize ( accounts. getSize ( ) + 1 ) ;
accounts[ accounts. getSize ( ) - 1 ] = account;
break ;
case 'd' :
cin >> index >> amount;
getline ( cin, desc) ;
accounts[ index] -> deposit ( date, amount, desc) ;
break ;
case 'w' :
cin >> index >> amount;
getline ( cin, desc) ;
accounts[ index] -> withdraw ( date, amount, desc) ;
break ;
case 's' :
for ( int i = 0 ; i < accounts. getSize ( ) ; i++ ) {
cout << "[" << i << "] " ;
accounts[ i] -> show ( ) ;
cout << endl;
}
break ;
case 'c' :
cin >> day;
if ( day < date. getDay ( ) )
cout << "You cannot specify a previous day" ;
else if ( day > date. getMaxDay ( ) )
cout << "Invalid day" ;
else
date = Date ( date. getYear ( ) , date. getMonth ( ) , day) ;
break ;
case 'n' :
if ( date. getMonth ( ) == 12 )
date = Date ( date. getYear ( ) + 1 , 1 , 1 ) ;
else
date = Date ( date. getYear ( ) , date. getMonth ( ) + 1 , 1 ) ;
for ( int i = 0 ; i < accounts. getSize ( ) ; i++ )
accounts[ i] -> settle ( date) ;
break ;
}
} while ( cmd != 'e' ) ;
for ( int i = 0 ; i < accounts. getSize ( ) ; i++ )
delete accounts[ i] ;
return 0 ;
}
package Bank9_16;
abstract class Account {
private String id;
private double balance;
private static double total = 0 ;
protected Account ( final Date date, final String id) {
this . id = id;
this . balance = 0 ;
date. show ( ) ;
System. out. println ( id + " created" ) ;
}
protected void record ( final Date date, double amount, final String desc) {
balance += amount;
total += amount;
date. show ( ) ;
System. out. println ( id + " " + amount + " " + balance + " " + desc) ;
}
protected void error ( final String msg) {
System. out. println ( "Error(#" + id + "):" + msg) ;
}
public String GetId ( ) {
return id;
}
public double GetBalance ( ) {
return balance;
}
public static double GetTotal ( ) {
return total;
}
public void show ( ) {
System. out. println ( id + " Balance:" + balance) ;
}
abstract void withdraw ( final Date date, double amount, final String desc) ;
abstract void deposit ( final Date date, double amount, final String desc) ;
abstract void settle ( final Date date) ;
}
class SavingsAccount extends Account {
private Accumulator acc;
private double rate;
public SavingsAccount ( final Date date, final String id, double rate) {
super ( date, id) ;
this . rate = rate;
acc = new Accumulator ( date, 0 ) ;
}
private double GatRate ( ) {
return rate;
}
void deposit ( final Date date, double amount, final String desc) {
record ( date, amount, desc) ;
acc. change ( date, GetBalance ( ) ) ;
}
void withdraw ( final Date date, double amount, final String desc) {
if ( amount > GetBalance ( ) ) {
error ( "not enough money" ) ;
}
else {
record ( date, - amount, desc) ;
acc. change ( date, GetBalance ( ) ) ;
}
}
void settle ( final Date date) {
double interest = acc. GetSum ( date) * rate/ date. distance ( new Date ( date. getYear ( ) - 1 , 1 , 1 ) ) ;
if ( interest != 0 ) {
record ( date, interest, "interest" ) ;
}
acc. reset ( date, GetBalance ( ) ) ;
}
}
class CreditAccount extends Account {
private Accumulator acc;
private double credit;
private double rate;
private double fee;
private double GetDebt ( ) {
double balance = GetBalance ( ) ;
return ( balance < 0 ? balance : 0 ) ;
}
public CreditAccount ( final Date date, final String id, double credit, double rate, double fee) {
super ( date, id) ;
this . credit = credit;
this . rate = rate;
this . fee = fee;
acc = new Accumulator ( date, 0 ) ;
}
public double GetCredit ( ) {
return credit;
}
public double GteRate ( ) {
return rate;
}
public double GetFee ( ) {
return fee;
}
public double GetAvailableCredit ( ) {
if ( GetBalance ( ) < 0 ) {
return credit + GetBalance ( ) ;
}
else {
return credit;
}
}
void deposit ( final Date date, double amount, final String desc) {
record ( date, amount, desc) ;
acc. change ( date, GetDebt ( ) ) ;
}
void withdraw ( final Date date, double amount, final String desc) {
if ( amount - GetBalance ( ) > credit) {
error ( "not enough credit" ) ;
}
else {
record ( date, - amount, desc) ;
acc. change ( date, GetDebt ( ) ) ;
}
}
void settle ( final 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 ( ) ) ;
}
public void show ( ) {
super . show ( ) ;
System. out. println ( "Available credit:" + GetAvailableCredit ( ) ) ;
}
}
package Bank9_16;
public class Accumulator {
private Date lastDate;
private double value;
private double sum;
public Accumulator ( final Date date, double value) {
this . lastDate = date;
this . value = value;
this . sum = 0 ;
}
public double GetSum ( final Date date) {
return sum + value * date. distance ( lastDate) ;
}
public void change ( final Date date, double value) {
sum = GetSum ( date) ;
lastDate = date;
this . value = value;
}
public void reset ( final Date date, double value) {
lastDate = date;
this . value = value;
sum = 0 ;
}
}
package Bank9_16;
public class Date {
private int year;
private int month;
private int day;
private int totalDays;
private int [ ] a = new int [ ] { 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 , 365 } ;
public Date ( int year, int month, int day) {
this . year = year;
this . month = month;
this . day = day;
if ( day <= 0 || day > this . getMaxDay ( ) ) {
System. out. println ( "Invalid date:" ) ;
this . show ( ) ;
System. exit ( 1 ) ;
}
int years = year - 1 ;
totalDays = years * 365 + years/ 4 - years/ 100 + years/ 400 + a[ month- 1 ] + day;
if ( this . LeapYear ( ) == true && month > 2 ) {
totalDays++ ;
}
}
public boolean LeapYear ( ) {
if ( ( year% 4 == 0 && year% 100 != 0 ) || ( year% 400 == 0 ) ) {
return true ;
}
else {
return false ;
}
}
public int getMaxDay ( ) {
if ( this . LeapYear ( ) == true && month == 2 ) {
return 29 ;
}
else {
return a[ month] - a[ month- 1 ] ;
}
}
public void show ( ) {
System. out. println ( year + "-" + month + "-" + day) ;
}
public int distance ( Date date) {
return totalDays - date. totalDays;
}
public int getYear ( ) {
return year;
}
public int getMonth ( ) {
return month;
}
public int getDay ( ) {
return day;
}
}
package Bank9_16;
import java. io. IOException;
import java. util. ArrayList;
import java. util. Scanner;
public class Run {
public static void main ( String[ ] args) throws IOException{
Date date = new Date ( 2008 , 11 , 1 ) ;
ArrayList< Account> accounts = new ArrayList < Account> ( 0 ) ;
System. out. println ( "(a)add account (d)deposit (w)withdraw (s)show (c)change day (n)next month (e)exit" ) ;
char cmd;
Scanner in = new Scanner ( System. in) ;
do {
date. show ( ) ;
System. out. println ( "\tTotal:" + Account. GetTotal ( ) + "\tcommand>" ) ;
char type;
int index, day;
double amount, credit, rate, fee;
String id, desc;
Account account;
cmd = ( char ) System. in. read ( ) ;
switch ( cmd) {
case 'a' :
type = ( char ) System. in. read ( ) ;
id = in. next ( ) ;
if ( type == 's' ) {
rate = in. nextDouble ( ) ;
account = new SavingsAccount ( date, id, rate) ;
} else {
credit = in. nextDouble ( ) ;
rate = in. nextDouble ( ) ;
fee = in. nextDouble ( ) ;
account = new CreditAccount ( date, id, credit, rate, fee) ;
}
accounts. add ( account) ;
accounts. trimToSize ( ) ;
break ;
case 'd' :
index = in. nextInt ( ) ;
amount = in. nextDouble ( ) ;
desc = in. nextLine ( ) ;
accounts. get ( index) . deposit ( date, amount, desc) ;
break ;
case 'w' :
index = in. nextInt ( ) ;
amount = in. nextDouble ( ) ;
desc = in. nextLine ( ) ;
accounts. get ( index) . withdraw ( date, amount, desc) ;
break ;
case 's' :
for ( int i = 0 ; i < accounts. size ( ) ; i++ ) {
System. out. println ( "[" + i + "]" ) ;
accounts. get ( i) . show ( ) ;
}
break ;
case 'c' :
day = in. nextInt ( ) ;
if ( day < date. getDay ( ) )
System. out. println ( "You cannot specify a previous day" ) ;
else if ( day > date. getMaxDay ( ) )
System. out. println ( "Invalid day" ) ;
else
date = new Date ( date. getYear ( ) , date. getMonth ( ) , day) ;
break ;
case 'n' :
if ( date. getMonth ( ) == 12 )
date = new Date ( date. getYear ( ) + 1 , 1 , 1 ) ;
else
date = new Date ( date. getYear ( ) , date. getMonth ( ) + 1 , 1 ) ;
for ( int i = 0 ; i < accounts. size ( ) ; i++ )
accounts. get ( i) . settle ( date) ;
break ;
}
} while ( cmd != 'e' ) ;
for ( int i = 0 ; i < accounts. size ( ) ; i++ )
accounts. remove ( i) ;
}
}
总结反思 这一个版本中,C语言中使用容器代替数组,而Java版本的代码中,使用"import java.util.ArrayList; import java.util.Scanner;"可实现这一功能。