15.12.2011, 04:07
общий
это ответ
Здравствуйте, joker!
Вот такая получилась реализация...
vklad.cpp
[code h=207]#include "vklad.h"
void CreateVklad();
void GetVklad();
void CloseVklad();
void ModifyVklad();
void GetInfo();
void CalcUSD();
void Exit();
void PutMoney(vklad *);
void GetMoney(vklad *);
void GetPercent(vklad *);
void ChangeCourse(vklad *);
void Exit(vklad *);
int GetNum();
int ViewMenu(char**, int);
bank *b = NULL; //все счета
char * mesMain[] = //сообщения меню
{
"Открыть новый счет",
"Показать состояние счета",
"Закрыть счет",
"Изменить счет",
"Все счета",
"Пересчет всех вкладов в валюту",
"Выход"
};
//количество пунктов меню
int MesMainCount = sizeof( mesMain ) / sizeof( mesMain[0] );
//функции отработки пунктов меню
void ( *funcMain[] )()={CreateVklad, GetVklad, CloseVklad,
ModifyVklad, GetInfo, CalcUSD, Exit};
char * mesModify[] =
{
"Внести деньги",
"Снять деньги",
"Снять проценты",
"Поменять курс",
"Выход"
};
//количество пунктов меню
int MesModifyCount = sizeof( mesModify ) / sizeof( mesModify[0] );
//функции отработки пунктов меню
void ( *funcModify[] )(vklad*)={PutMoney, GetMoney, GetPercent, ChangeCourse, Exit};
void CreateVklad() //создание вклада
{
char str[64] = {0};
int num = 0;
int months = 0;
double sum = 0;
double percent = 0;
double course = 0;
if (b == NULL) //проверим наличие банка
{ //нет - создадим
cout << endl << "Создаем банк. Введите курс USD: ";
do
{
cin.getline(str, sizeof(str),'\n');
course = atof(str);
}while (str[0] == 0 || course == 0);
b = new bank(course); //создаем банк
}
else
course = b->GetCourse(); //курс берем в банке
//запросим тип счета
cout << endl << "Введите тип счета:" << endl;
v_type type = (v_type)(ViewMenu(typeStr, type_count)-1);
//номер счета
cout << "Введите номер счета: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
num = atol(str);
}while (str[0] == 0 || num == 0);
//сумма
cout << "Введите сумму: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
sum = atof(str);
}while (str[0] == 0 || sum == 0);
//процент
cout << "Введите процент: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
percent = atof(str);
}while (str[0] == 0 || percent == 0);
switch (type)
{
case normal:
b->Add(new Normal(sum, percent), num);
break;
case monetary:
b->Add(new Monetary(sum, percent, course), num);
break;
case forward:
//заносим число месяцев
cout << "Введите срок хранения (в месяцах): ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
months = atol(str);
}while (str[0] == 0 || months == 0);
b->Add(new Forward(sum, percent, months), num);
}
}
void GetVklad()
{
char str[64] = {0};
int num = 0;
vklad *vkl;
//номер счета
cout << "Введите номер счета: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
num = atol(str);
}while (str[0] == 0 || num == 0);
vkl = b->GetVklad(num);
if (vkl)
{
vkl->handle->CalcVklad(vkl->handle->GetCurrentDate());
vkl->handle->View();
}
else
cout << "Такого счета нет" << endl;
}
void CloseVklad()
{
char str[64] = {0};
int num = 0;
vklad *vkl;
cout << "Введите номер счета: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
num = atol(str);
}while (str[0] == 0 || num == 0);
vkl = b->GetVklad(num);
if (vkl)
{
vkl->handle->Close(vkl->handle->GetCurrentDate());
}
else
cout << "Такого счета нет" << endl;
}
void ModifyVklad()
{
char str[64] = {0};
int ret, num = 0;
vklad *vkl;
cout << endl << "Введите номер счета: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
num = atol(str);
}while (str[0] == 0 || num == 0);
vkl = b->GetVklad(num);
if (vkl)
{
if (vkl->handle->IsOpen())
{
do
{
ret = ViewMenu(mesModify, MesModifyCount);
funcModify[ret-1](vkl);
if (ret == MesModifyCount)
break;
cout << endl;
}while ( ret );
}
else
cout << "Счет закрыт" << endl;
}
else
cout << "Такого счета нет" << endl;
}
void PutMoney(vklad *vkl)
{
try
{
char str[64] = {0};
double sum = 0;
if (vkl->handle->GetType() == forward)
throw "На срочный вклад нельзя вносить деньги";
if (!vkl->handle->IsOpen())
throw "На закрытый счет нельзя внести деньги";
vkl->handle->CalcVklad(vkl->handle->GetCurrentDate());
cout << endl << "Введите сумму: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
sum = atof(str);
}while (str[0] == 0 || sum == 0);
vkl->handle->SetSum(vkl->handle->GetSum() + sum);
}
catch(char * str)
{
cout << str << endl;
}
}
void GetMoney(vklad *vkl)
{
try
{
char str[64] = {0};
double sum = 0;
double sum_vklad;
vkl->handle->CalcVklad(vkl->handle->GetCurrentDate());
sum_vklad = vkl->handle->GetSum();
if ((vkl->handle->GetType() == forward) && vkl->handle->IsOpen())
throw "C открытого срочного вклада нельзя снять деньги";
cout << "Введите сумму, которую хотите снять: ";
do
{
str[0] = 0;
cin.getline(str, sizeof(str),'\n');
sum = atof(str);
}while (str[0] == 0 || sum == 0);
if ((vkl->handle->GetType() == forward) && (sum_vklad != sum))
throw "Cо срочного вклада можно снять только все деньги сразу";
if (sum > sum_vklad)
throw "Денег на счету меньше, чем Вы хотите снять";
sum_vklad -= sum;
vkl->handle->SetSum(sum_vklad);
cout << "Получите " << sum;
if (vkl->handle->GetType() == monetary)
cout << " " << ((Monetary*)vkl->handle)->GetCurrency();
else
cout << " RUR";
cout << endl;
}
catch(char * str)
{
cout << str << endl;
}
}
void GetPercent(vklad *vkl)
{
try
{
char str[64] = {0};
double sum;
double sum_vklad;
if (!vkl->handle->IsOpen())
throw "C закрытого вклада нельзя снять проценты";
vkl->handle->CalcVklad(vkl->handle->GetCurrentDate());
sum_vklad = vkl->handle->GetSum();
sum = vkl->handle->GetSumPercent();
vkl->handle->SetSum(sum_vklad - sum);
cout << "Получите " << sum;
if (vkl->handle->GetType() == monetary)
cout << " " << ((Monetary*)vkl->handle)->GetCurrency();
else
cout << " RUR";
cout << endl;
}
catch(char * str)
{
cout << str << endl;
}
}
void ChangeCourse(vklad *vkl)
{
double course = 0;
char str[64] = {0};
cout << "Введите курс USD: ";
do
{
cin.getline(str, sizeof(str),'\n');
course = atof(str);
}while (str[0] == 0 || course == 0);
b->SetCourse(course);
}
void Exit(vklad *vkl){}
//вывод информации о счетах
void GetInfo()
{
try
{
if (b)
b->View();
else
throw "Сначала откройте счет!";
}
catch(char * str)
{
cout << str << endl;
}
}
void CalcUSD()
{
vklad * vkl;
cout << "Пересчёт вкладов, хранящихся на всех счетах, в USD:" << endl;
for (vkl=b->first(); vkl!=NULL; vkl=b->next())
{
vkl->handle->CalcVklad(vkl->handle->GetLastDate());
if (vkl->handle->GetType() == monetary)
cout << "Счет №" << vkl->num << ":\t" <<
vkl->handle->GetSum() << " " << ((Monetary*)vkl->handle)->GetCurrency() << endl;
else
cout << "Счет №" << vkl->num << ":\t" <<
(double)((int)((vkl->handle->GetSum()/b->GetCourse())*100)/100) << " USD" << endl;
}
}
void Exit(){}
int GetNum()
{
int a;
cin >> a;
while ( !( cin.good() || cin.eof() ) || ( a < 0 ) )
{
cout << "Введите число! " << endl;
cin.clear();
cin.ignore();
cin >> a;
}
return a;
}
int ViewMenu(char** mes, int max)
{
int ret;
do
{
for ( int i = 0; i < max; i++ )
cout << i+1 << ". " << mes[i] << endl;
cout << "Ваш выбор: ";
ret = GetNum();
}
while ( ret < 1 || ret > max );
return ret;
}
int main()
{
setlocale(LC_ALL,"Russian");
int ret;
do
{
ret = ViewMenu(mesMain, MesMainCount);
funcMain[ret-1]();
cout << endl;
if (ret == MesMainCount)
break;
}while ( ret );
delete b;
system("pause");
return 0;
}
[/code]
vklad.h
[code h=207]#include <windows.h>
#include <locale>
#include <iostream>
#include <list>
#include <string.h>
using namespace std;
//тип вклада
enum v_type
{
normal,
monetary,
forward,
type_count
};
char *typeStr[type_count] =
{
"обычный",
"валютный",
"срочный"
};
struct VDATE
{
unsigned char day;
unsigned char month;
unsigned short year;
};
class Normal
{
private:
v_type _Type;
double _Sum;
double _SumFirst;
VDATE *_CreateDate;
VDATE *_LastDate;
double _Percent;
bool _open;
public:
Normal(double sum, double percent, v_type type=normal)
{
_Type = type;
_Sum = sum;
_SumFirst = sum;
_CreateDate = GetCurrentDate();
_LastDate = GetCurrentDate();
_Percent = percent;
_open = true;
}
~Normal()
{
delete _CreateDate;
delete _LastDate;
}
friend class Monetary;
inline v_type GetType(){return _Type;}
inline double GetSum(){return _Sum;}
inline double GetSumPercent(){return (_Sum-_SumFirst);}
inline void SetSum(double sum){_Sum = sum;}
inline VDATE* GetCreateDate(){return _CreateDate;}
inline VDATE* GetLastDate(){return _LastDate;}
inline void SetLastDate(VDATE *date){*_LastDate = *date;}
inline double GetPercent(){return _Percent;}
inline bool IsOpen(){return _open;}
virtual void Close(VDATE *pdate)
{
if (_open)
{
CalcVklad(pdate);
_open = false;
}
}
VDATE* GetCurrentDate()
{
SYSTEMTIME st;
VDATE *dt = new VDATE;
GetLocalTime(&st);
dt->day = (unsigned char)st.wDay;
dt->month = (unsigned char)st.wMonth;
dt->year = (unsigned short)st.wYear;
return dt;
}
virtual void CalcVklad(VDATE *pdate)
{
try
{
int days = pdate->day - _LastDate->day;
int months = pdate->month - _LastDate->month;
int years = pdate->year - _LastDate->year;
if (!IsOpen())
throw "Для закрытого счета рассчитать величину начислений невозможно";
if (days < 0)
{
days += 30;
months--;
}
if (months < 0)
{
months += 12;
years--;
}
if (years < 0)
throw "Неверно задана дата";
_Sum += _Sum * (((years*12 + months) + ((double)days)/30)) * _Percent / 100;
_Sum = ((double)((int)(_Sum * 100)))/100;
SetLastDate(pdate);
}
catch(char * str)
{
cout << str << endl;
}
}
bool SetClose(Normal * v);
virtual void View()
{
char str[32];
cout << endl << "Счет\t\t";
if (_open)
cout << "открыт";
else
cout << "закрыт";
cout << endl << "Тип вклада:\t" << typeStr[_Type] << endl;
cout << "Сумма:\t\t" << _Sum << endl;
sprintf(str, "%02d.%02d.%04d", _CreateDate->day, _CreateDate->month, _CreateDate->year);
cout << "Дата создания:\t" << str << endl;
sprintf(str, "%02d.%02d.%04d", _LastDate->day, _LastDate->month, _LastDate->year);
cout << "Дата изменения:\t" << str << endl;
sprintf(str, "%5.2f%%", _Percent);
cout << "Процент:\t" << str << endl;
};
};
class Monetary: public Normal
{
private:
char *_Currency;
double _Course;
public:
Monetary(double sum, double percent, double course, char *currency = "USD")
:Normal(sum, percent, monetary)
{
if (currency)
{
_Currency = new char[strlen(currency)+1];
strcpy(_Currency, currency);
}
_Course = course;
}
~Monetary(){delete _Currency;}
virtual void View()
{
char str[32];
Normal::View();
cout << "Валюта:\t\t" << _Currency << endl;
sprintf(str, "%5.2f", _Course);
cout << "Курс:\t\t" << str << endl;
cout << "Сумма в рублях:\t" << GetRub() << endl;
};
inline double GetRub(){return GetSum() * _Course;}
inline void SetCourse(double c){_Course = c;}
inline char * GetCurrency(){return _Currency;}
};
class Forward: public Normal
{
private:
int _MonthCount;
int _MonthBalance;
public:
Forward(double sum, double percent, int months)
:Normal(sum, percent, forward)
{
_MonthCount = months;
_MonthBalance = months;
}
virtual void CalcVklad(VDATE *pdate)
{
try
{
VDATE *last = GetLastDate();
int days = pdate->day - last->day;
int months = pdate->month - last->month;
int years = pdate->year - last->year;
if (!IsOpen())
throw "Для закрытого счета рассчитать величину начислений невозможно";
if (days < 0)
{
days += 30;
months--;
}
if (months < 0)
{
months += 12;
years--;
}
if (years < 0)
throw "Неверно задана дата";
int monthcount = (years*12 + months) + (days/30) ;
if (monthcount)
{
if (monthcount > _MonthBalance)
monthcount = _MonthBalance;
int sum = GetSum();
sum += sum * monthcount * GetPercent() / 100;
sum = ((double)((int)(sum * 100)))/100;
SetSum(sum);
_MonthBalance -= monthcount;
last->month += monthcount;
while (last->month > 12)
{
last->month -= 12;
last->year++;
}
SetLastDate(last);
SetClose(this);
}
}
catch(char * str)
{
cout << str << endl;
}
}
inline int GetTail(){return _MonthBalance;}
virtual void Close(VDATE *pdate)
{
if (IsOpen())
CalcVklad(pdate);
}
virtual void View()
{
Normal::View();
cout << "Срок хранения:\t" << _MonthCount << " мес" << endl;
};
};
bool Normal::SetClose(Normal * v)
{
if (v->GetType() == forward && ((Forward*)v)->GetTail() == 0)
{
_open = false;
return true;
}
return false;
}
struct vklad
{
int num;
Normal *handle;
};
class bank //класс банка
{
private:
double _course;
list <vklad*> table; //таблица вкладов
list <vklad*>::iterator it; //итератор для работы со списком
public:
bank(double course=0){_course = course;}
~bank()
{
for(it=table.begin(); table.size(); it=table.begin())
{
delete (*it)->handle;
table.erase(it);
}
}
bool Add(Normal * vkl, int n) //добавление
{
int i;
//ищем, куда ставить, чтобы было отсортировано (сортировка вставкой)
//по всем вкладам
for(it=table.begin(); it!=table.end(); it++)
{
//сравним номера счетов
i = (*it)->num - n;
if (i == 0) //равны - такой уже есть. Предполагаем, что все разные
return FALSE;
else if (i > 0) //больше - сюда вставляем
break;
} //или в конец списка
vklad * v = new vklad;
v->num = n;
v->handle = vkl;
table.insert(it, v); //вставляем в таблицу
return TRUE; //отработали
}
bool Del(int n) //удаление
{
int i;
//ищем по всем вкладам
for(it=table.begin(); it!=table.end(); it++)
{
//сравним номера счетов
i = (*it)->num - n;
if (i == 0)
{
delete (*it)->handle;
table.erase(it);
return true;
}
else if (i > 0) //больше - сюда вставляем
break;
}
return false;
}
void SetCourse(double course)
{
_course = course;
for(it=table.begin(); it!=table.end(); it++)
{
if ((*it)->handle->GetType() == monetary)
((Monetary*)((*it)->handle))->SetCourse(course);
}
}
inline double GetCourse(){return _course;}
vklad * GetVklad(int n)
{
int i;
for(it=table.begin(); it!=table.end(); it++)
{
i = (*it)->num - n;
if (i == 0)
return (*it); //равно - наш вклад
else if (i > 0)
break;
}
return NULL; //0 - не нашли
}
//показ всей инфы по всем вкладам
void View()
{
cout << endl << "Таблица вкладов" << endl;
cout << "Всего: " << table.size() << endl;
//вывод инфы о каждом вкладе
for(it=table.begin(); it!=table.end(); it++)
{
cout << endl << "Номер счета: " << (*it)->num << endl;
(*it)->handle->View();
}
}
vklad * first()
{
it = table.begin();
if (it != table.end())
return (*it);
else
return NULL;
}
vklad * next()
{
it++;
if (it != table.end())
return (*it);
else
return NULL;
}
};
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен