Все выпуски  

RFpro.ru: Программирование на C / C++


Хостинг портала RFpro.ru:
Московский хостер
Профессиональный ХОСТИНГ на базе Linux x64 и Windows x64

РАССЫЛКИ ПОРТАЛА RFPRO.RU

Лучшие эксперты по данной тематике

Асмик Гаряка
Статус: Академик
Рейтинг: 8743
∙ повысить рейтинг »
Коцюрбенко Алексей aka Жерар
Статус: Профессор
Рейтинг: 3192
∙ повысить рейтинг »
Boriss
Статус: Академик
Рейтинг: 2596
∙ повысить рейтинг »

/ КОМПЬЮТЕРЫ И СОФТ / Программирование / C/C++

Номер выпуска:1707
Дата выхода:15.12.2011, 18:30
Администратор рассылки:Киселёва Алёна aka Verena (Профессор)
Подписчиков / экспертов:279 / 163
Вопросов / ответов:1 / 1

Консультация # 184640: Уважаемые эксперты! Пожалуйста, ответьте на вопрос: Среда - Visual Studio 2005-2007 Необходимо разработать приложение с 3 видами вкладов используя классы. Операции для обычныго и валютного вкладов могут выполняться с частью вклада, а для срочных - только со всем вкладом.Каждый вклад реализовать своим описателем. Описатель обычного в...


Консультация # 184640:

Уважаемые эксперты! Пожалуйста, ответьте на вопрос:
Среда - Visual Studio 2005-2007
Необходимо разработать приложение с 3 видами вкладов используя классы.
Операции для обычныго и валютного вкладов могут выполняться с частью вклада, а для срочных - только со всем вкладом.Каждый вклад реализовать своим описателем.

Описатель обычного вклада содержит: сумму вклада, дату открытия вклада и дату последней onepaции с вкладом;процент начисления по вкладу (ежемесячный, т.е. начисления на вклад выполняются, начиная от даты последнего изменения по текущую дату, которая передаётся в метод).
Описатель срочного вклада содержит: сумму вклада, дату открытия вклада и срок хранения, процент начисления по вкладу (ежемесячный).
Описатель валютного вклада содержит: название валюты, сумму вклада, дату открытия вклада и дату последней операции с вкладом, курс обмена, процент начисления по вкладу (ежемесячный, начиная от деле последней операции).

Каждый вклад имеет уникальную характеристику - номер счёта. Информация обо всех вкладах сведена в таблицу, каждый элемент которой состоит из номера счёта и указателя на описатель вклада. Элементы таблицы упорядочены по возрастанию номеров вкладов.
Функции таблицы:
включить новый элемент в таблицу, не нарушая упорядоченности;
найти элемент в таблице по номеру счёта;
исключить элемент из таблицы по номеру счёта;
показать содержимое таблицы.
Для любого вклада:
получить (вернуть в качестве результата) сумму вклада; изменить сумму вклада;
рассчитать величину начислений по процентам;
получить дату открытия вклада;
получить дату последней операции; изменить дату последней операции;
показать всю информацию о вкладе,
Для валютного вклада;
выполнить пересчёт суммы вклада в рублях
Для приложения:
открыть новый счёт;
показать текущее состояние счёта (с начислением процентов по состоянию на текущую дату);
закрыть счёт (с начислением процентов п о состоянию на текущую дату);
модифицировать состояние счёта (внести деньги, снять вклад, снять проценты);
показать информацию обо всех имеющихся счётах;
выполнить пересчёт вкладов, хранящихся на всех счетах, в указанную валюту, используя класс-итератор.

Этапы выполнения
1.На основе описания задачи определить состав классов.
2.Разработать иерархию классов и схему их взаимодействия.
3.Для каждого класса определить его состояние и необходимые методы.
4.Разработать и отладить все классы. Приложение реализовать в виде простой диалоговой программы.
5.Разработать и отладить класс, реализующий работу приложения. Предусмотреть в классе возможность сохранения таблицы в файле и ее восстановления.
Опционально
Повторить разработку контейнерного класса (вместе с необходимыми итераторами), используя - стандартную библиотеку STL.
Повторить разработку контейнерного класса (вместе с необходимыми итераторами), используя собственные шаблоны классов.
< br>Код желательно прокомментировать. Огромное спасибо за внимание!

Дата отправки: 01.12.2011, 18:01
Вопрос задал: joker (Посетитель)
Всего ответов: 1
Страница онлайн-консультации »


Консультирует Лысков Игорь Витальевич (Старший модератор):

Здравствуйте, joker!

Вот такая получилась реализация...

vklad.cpp

Код :
#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;
}


vklad.h
Код :
#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;
	}
};

Консультировал: Лысков Игорь Витальевич (Старший модератор)
Дата отправки: 15.12.2011, 04:07
Рейтинг ответа:

НЕ одобряю 0 одобряю!


Оценить выпуск | Задать вопрос экспертам

главная страница  |  стать участником  |  получить консультацию
техническая поддержка  |  восстановить логин/пароль

Дорогой читатель!
Команда портала RFPRO.RU благодарит Вас за то, что Вы пользуетесь нашими услугами. Вы только что прочли очередной выпуск рассылки. Мы старались. Пожалуйста, оцените его. Если совет помог Вам, если Вам понравился ответ, Вы можете поблагодарить автора - для этого в каждом ответе есть специальные ссылки. Вы можете оставить отзыв о работе портале. Нам очень важно знать Ваше мнение. Вы можете поближе познакомиться с жизнью портала, посетив наш форум, почитав журнал, который издают наши эксперты. Если у Вас есть желание помочь людям, поделиться своими знаниями, Вы можете зарегистрироваться экспертом. Заходите - у нас интересно!
МЫ РАБОТАЕМ ДЛЯ ВАС!



В избранное