// Компилировать с включеной информацией о типах времени выполнения
// Для MS VS это /GR
#include <locale>
#include <limits>
#include <iostream>
#include <iomanip>
#include <deque>
#include <valarray>
#include <stdexcept>
#include <cfloat>
#include <typeinfo>
#include <sstream>
#include <string>
using namespace std;
// Программа работает по принципу калькулятора с обратной(польской) записью
// Этот класс здесь исключительно для полиморфизма и возможности выводить/хранить
// в регистрах как числа, так и вектора
class register_object
{
public:
virtual string to_string() const=0;
virtual ~register_object(){};
};
// Собственно вектор
class my_vector:public register_object
{
public:
// Конструктор
explicit my_vector(double dx=0,double dy=0,double dz=0);
// Деструктор
virtual ~my_vector();
// Оператор сложения
my_vector operator+(const my_vector& right) const;
// Оператор вычитания
my_vector operator-(const my_vector& right) const;
// Скалярное произведение
double operator*(const my_vector& right) const;
// Длина вектора
double length() const;
// Выводит на экран
virtual string to_string() const;
// Сосинус между векторами
friend double cos(const my_vector& left,const my_vector& right);
// Оператор вывода
template<class Elem,class Traits> friend basic_istream<Elem,Traits>& operator>>(basic_istream<Elem,Traits>& stream,my_vector& vec);
private:
double _dx,_dy,_dz;
};
// Служит для хранения в регистрах калькулятора чисел типа double
class my_num:public register_object
{
public:
explicit my_num(double val=0);
virtual ~my_num();
virtual string to_string() const;
private:
double _val;
};
// Собственно программа
class application
{
public:
~application();
void run();
private:
// Возможный выбор пользователя
enum user_choice
{
INPUT,
PLUS,
MINUS,
SCALAR,
LENGTH,
COS,
DELETE,
QUIT
};
// Меню
user_choice menu();
// Ввод вектора
my_vector input_vector();
// Печать регистров калькулятора
void print_registers();
// Сложение векторов
my_vector plus_operation();
// Вычитание векторов
my_vector minus_operation();
// Скалярное произведение
double scalar_operation();
// Длина
double length_operation();
// Косинус
double cos_operation();
typedef deque<register_object*> register_stack;
typedef register_stack::const_reverse_iterator rev_it;
// Здесь будем хранить значения
register_stack registers;
void check_registers(register_stack::size_type count) const;
void delete_registers(register_stack::size_type count);
};
int main()
{
locale::global(locale(""));
application app;
app.run();
return 0;
}
my_vector::my_vector( double dx/*=0*/,double dy/*=0*/,double dz/*=0*/ )
:_dx(dx)
,_dy(dy)
,_dz(dz)
{}
my_vector my_vector::operator+( const my_vector& right ) const
{
return my_vector(_dx+right._dx,_dy+right._dy,_dz+right._dz);
}
my_vector my_vector::operator-( const my_vector& right ) const
{
return my_vector(_dx-right._dx,_dy-right._dy,_dz-right._dz);
}
double my_vector::operator*( const my_vector& right ) const
{
return _dx*right._dx+_dy*right._dy+_dz*right._dz;
}
double my_vector::length() const
{
return sqrt(_dx*_dx+_dy*_dy+_dz*_dz);
}
string my_vector::to_string() const
{
stringstream sstream;
sstream<<'('<<_dx<<','<<_dy<<','<<_dz<<')';
return sstream.str();
}
my_vector::~my_vector()
{
}
double cos( const my_vector& left,const my_vector& right )
{
double result=left*right/left.length()/right.length();
if(!_finite(result))
{
throw runtime_error("Невозможно вычислить косинус");
}
return result;
}
template<class Elem,class Traits>
basic_istream<Elem,Traits>& operator>>(basic_istream<Elem,Traits>& stream,my_vector& vec)
{
double dx,dy,dz;
stream>>dx>>dy>>dz;
if(!stream.fail())
{
vec._dx=dx;
vec._dy=dy;
vec._dz=dz;
}
return stream;
}
my_num::my_num( double val/*=0*/ )
:_val(val)
{
}
string my_num::to_string() const
{
stringstream sstream;
sstream<<_val;
return sstream.str();
}
my_num::~my_num()
{
}
application::~application()
{
// Освободим память.
// Т.к. полиморфизм работает через указатели/ссылки мы ее выреляли динамически
while(!registers.empty())
{
delete registers.front();
registers.pop_front();
}
}
void application::run()
{
user_choice choice;
// Реакция на ввод пользователя
while((choice=menu())!=QUIT)
{
try
{
switch(choice)
{
case INPUT:
{
registers.push_front(new my_vector(input_vector()));
break;
}
case PLUS:
{
my_vector tmp=plus_operation();
delete_registers(2);
registers.push_front(new my_vector(tmp));
break;
}
case MINUS:
{
my_vector tmp=minus_operation();
delete_registers(2);
registers.push_front(new my_vector(tmp));
break;
}
case SCALAR:
{
double tmp=scalar_operation();
delete_registers(2);
registers.push_front(new my_num(tmp));
break;
}
case LENGTH:
{
double tmp=length_operation();
delete_registers(1);
registers.push_front(new my_num(tmp));
break;
}
case COS:
{
double tmp=cos_operation();
delete_registers(2);
registers.push_front(new my_num(tmp));
break;
}
case DELETE:
{
delete_registers(1);
break;
}
}
}
catch(const runtime_error& ex)
{
cout<<ex.what()<<endl;
}
catch(...)
{
cout<<"Необработанное исключение"<<endl;
}
print_registers();
}
}
application::user_choice application::menu()
{
while(true)
{
cout<<"Меню:"<<endl
<<"1 - Ввод вектора"<<endl
<<"2 - Сложить"<<endl
<<"3 - Вычесть"<<endl
<<"4 - Скалярное произведение"<<endl
<<"5 - Длина вектора"<<endl
<<"6 - Косинус угла между векторами"<<endl
<<"7 - Удалить последнее значение"<<endl
<<"0 - Выход"<<endl
<<"Ваш выбор:";
wint_t choice=_getwche();
cout<<endl<<endl;
switch(choice)
{
case '0':
return QUIT;
case '1':
return INPUT;
case '2':
return PLUS;
case '3':
return MINUS;
case '4':
return SCALAR;
case '5':
return LENGTH;
case '6':
return COS;
case '7':
return DELETE;
default:
cout<<"Будьте внимательней"<<endl;
}
}
}
my_vector application::input_vector()
{
my_vector res;
cout<<"Введите координаты вектора(dx,dy,dz):";
cin>>res;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
throw runtime_error("Ошибочный ввод");
}
return res;
}
void application::print_registers()
{
if(registers.size())
{
cout<<"------------------------------"<<endl;
cout<<"Стек регистров калькулятора:"<<endl;
cout<<"------------------------------"<<endl;
register_stack::size_type i=registers.size();
while(i--)
{
cout<<setw(14)<<left<<(i?"":"Результат:")<<registers[i]->to_string()<<endl;
}
cout<<"------------------------------"<<endl;
}
}
my_vector application::plus_operation()
{
check_registers(2);
return *dynamic_cast<my_vector*>(registers[0])+*dynamic_cast<my_vector*>(registers[1]);
}
my_vector application::minus_operation()
{
check_registers(2);
return *dynamic_cast<my_vector*>(registers[1])-*dynamic_cast<my_vector*>(registers[0]);
}
double application::scalar_operation()
{
check_registers(2);
return *dynamic_cast<my_vector*>(registers[1])**dynamic_cast<my_vector*>(registers[0]);
}
double application::length_operation()
{
check_registers(1);
return dynamic_cast<my_vector*>(registers[0])->length();
}
double application::cos_operation()
{
check_registers(2);
return cos(*dynamic_cast<my_vector*>(registers[0]),*dynamic_cast<my_vector*>(registers[1]));
}
// Проверяет требуемое количество регистров на наличие в них векторов, а не, например, чисел
void application::check_registers( register_stack::size_type count ) const
{
stringstream sstream;
if(registers.size()<count)
{
sstream<<"Требуется "<<count<<" операнд(а)";
throw runtime_error(sstream.str());
}
for(register_stack::size_type i=0;i<count;++i)
{
// Проверка на соответствие по типу указателя
if(typeid(*registers[i])!=typeid(my_vector))
{
sstream<<"Требуется "<<count<<" вектор(а)";
throw runtime_error(sstream.str());
}
}
}
// Очищает требуемое количество регистров
void application::delete_registers( register_stack::size_type count )
{
if(count>registers.size())
{
count=registers.size();
}
while(count--)
{
delete registers.front(); registers.pop_front();
}
}
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:1
Введите координаты вектора(dx,dy,dz):1 2 3
------------------------------
Стек регистров калькулятора:
------------------------------
Результат: (1,2,3)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:1
Введите координаты вектора(dx,dy,dz):3 4 5
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
Результат: (3,4,5)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:1
Введите координаты вектора(dx,dy,dz):0 5 0
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
Результат: (0,5,0)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:1
Введите координаты вектора(dx,dy,dz):1 0 0
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
Результат: (1,0,0)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:1
Введите координаты вектора(dx,dy,dz):2 4 6
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
(1,0,0)
Результат: (2,4,6)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:1
Введите координаты вектора(dx,dy,dz):9 8 6
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
(1,0,0)
(2,4,6)
Результат: (9,8,6)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:1
Введите координаты вектора(dx,dy,dz):7 7 7
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
(1,0,0)
(2,4,6)
(9,8,6)
Результат: (7,7,7)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:5
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
(1,0,0)
(2,4,6)
(9,8,6)
Результат: 12,1244
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:7
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
(1,0,0)
(2,4,6)
Результат: (9,8,6)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:4
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
(1,0,0)
Результат: 86
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:7
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
(0,5,0)
Результат: (1,0,0)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:6
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
(3,4,5)
Результат: 0
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:7
------------------------------
Стек регистров калькулятора:
------------------------------
(1,2,3)
Результат: (3,4,5)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:2
------------------------------
Стек регистров калькулятора:
------------------------------
Результат: (4,6,8)
------------------------------
Меню:
1 - Ввод вектора
2 - Сложить
3 - Вычесть
4 - Скалярное произведение
5 - Длина вектора
6 - Косинус угла между векторами
7 - Удалить последнее значение
0 - Выход
Ваш выбор:
void dlina(vector3D *vec1); // вычисляет длину вектора
void scalar(vector3D *vec1, vector3D *vec2); // скалярно умножает вектора
void cosinus(vector3D *vec1, vector3D *vec2); // выводит косинус угла между векторами
Если Вы уже зарегистрированы на Портале - войдите в систему, если Вы еще не регистрировались - пройдите простую процедуру регистрации.