/********************************************************************
My simple calculator.
In this file are methods of Class 'Calculator'.
********************************************************************/
//-------------------------------------------
#include "std_lib_facilities.h"
//-------------------------------------------
#include "header.h"
//-------------------------------------------
using namespace std;
//-------------------------------------------
// The greeting at the start
void Calculator::welcome()
{
cout << "Welcome to the calculator program!\n";
cout << "Please 'info' or 'help' for getting help.";
cout << "\nEnter an expression:\n\n";
}
//-------------------------------------------
// Deleting data from a class
void Calculator::cleardate()
{
str = " ";
str_part = " ";
t.kind = ' ';
t.name = " ";
t.value = 0;
tok.clear();
}
//-------------------------------------------
// Read user data
void Calculator::get()
{
vars.var_table_intial_value();
cin >> str;
strexpression(str,t,tok);
if( nocalculation == false ){
validationstrexpression();
result = calculation();
}
cleardate();
}
void Calculator::get( string &str )
{
vars.var_table_intial_value();
cin >> str;
strexpression(str,t,tok);
if( nocalculation == false ){
validationstrexpression();
result = calculation();
}
cleardate();
}
//-------------------------------------------
// The output
void Calculator::out()
{
if( nocalculation == false ) cout << "= " << result << "\n";
else nocalculation = false;
}
//-------------------------------------------
/********************************************
Convert user string into tokens.
********************************************/
//-------------------------------------------
// Parsing custom string
void Calculator::strexpression( string &str, Calculatortoken &t, vector<Calculatortoken> &tok )
{
int brace_open = 0;
int brace_close = 0;
vector<int> brace_minusone;
bool figurebrace_minusone = false;
int figurebrace_open = 0;
int figurebrace_close = 0;
for( int i = 0 ; i < str.size() ; ++i ){
switch( str[i] ){
case '+':
char_plus(i); break;
case '-':
char_minus(i,brace_open,brace_minusone,figurebrace_minusone); break;
case '*':
char_multiply(i); break;
case '/':
char_divide(i); break;
case '%':
char_percent(i); break;
case '!':
char_exclamation(i); break;
case '(':
char_roundbrace_open(i,brace_open); break;
case ')':
char_roundbrace_close(i,brace_open,brace_close,brace_minusone); break;
case '{':
char_figurebrace_open(i,figurebrace_open); break;
case '}':
char_figurebrace_close(i,figurebrace_open,figurebrace_close,brace_close,figurebrace_minusone,brace_minusone); break;
case '.':
char_point(); break;
case ',':
char_separator(i); break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if( i > 0 && (( int(str[i-1]) >= 65 && int(str[i-1]) <= 90 ) || ( int(str[i-1]) >= 97 && int(str[i-1]) <= 122 )) ){ char_letter(i); break; }
else{ char_number(i); break; }
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_':
char_letter(i); break;
case '=':
char_equal(i); break;
default:
throw errordefault(); break;
}
if( str_part == "info" || str_part == "help" ){
nocalculation = true;
vars.variable_info();
cleardate();
}else if( i == str.size()-1 &&
tok[tok.size()-1].kind != number &&
tok[tok.size()-1].kind != ')' &&
tok[tok.size()-1].kind != '}' &&
tok[tok.size()-1].kind != '!' ){
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
}
}
//strnum_cout();
}
//-------------------------------------------
// Determination of the number (false) of variable (true) in the string
bool Calculator::variable_or_number()
{
for( int i = 0 ; i < str_part.size() ; ++i ){
if( ( int(str_part[i]) >= 65 && int(str_part[i]) <= 90 ) || ( int(str_part[i]) >= 97 && int(str_part[i]) <= 122 ) ) return true;
}
return false;
}
//-------------------------------------------
// The addition symbol in the string
void Calculator::char_plus( int i )
{
if( str_part != " " ){
if( i+1 < str.size() && str[i+1] != ')' && str[i+1] != '}' ){
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
putintoken(t,tok,'+');
}
}else if( str_part == " " ){
if( i != 0 ){
if( int(str[i-1]) >= 0 && int(str[i-1]) != ')' && int(str[i-1]) != '}' && int(str[i-1]) != '!' ){
str_part = "+";
}else{
if( i+1 < str.size() && str[i+1] != ')' && str[i+1] != '}' && str[i+1] != '!' )
putintoken(t,tok,'+');
}
}
}
}
//-------------------------------------------
// The difference symbol in the string
void Calculator::char_minus( int i, int &brace_open, vector<int> &brace_minusone, bool &figurebrace_minusone )
{
if( str_part != " " ){
if( i+1 < str.size() && ( str[i+1] != ')' || str[i+1] != '}' || str[i+1] != '!' ) ){
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
putintoken(t,tok,'-');
}
}else if( str_part == " " ){
if( ( i == 0 && ( str[i+1] == '(' || str[i+1] == '{' || str[i+1] == '!' ) ) ||
( i > 0 && i+1 < str.size() &&
( str[i-1] != ')' && str[i-1] != '}' && str[i-1] != '!' ) &&
( str[i+1] == '(' || str[i+1] == '{' || str[i+1] == '!' )) ){
putintoken(t,tok,'(', ++brace_open);
brace_minusone.push_back(brace_open);
if( str[i+1] == '{' ) figurebrace_minusone = true;
if( variable_or_number() == true )
putintoken(t,tok,variable,-1);
else
putintoken(t,tok,number,-1);
putintoken(t,tok,'*');
}else if( ( i == 0 && i+1 < str.size() && str[i+1] != '(' && str[i+1] != '{' && str[i+1] != '!' ) || ( i-1 >= 0 && str[i-1] != ')' && str[i-1] != '}' && str[i-1] != '!' ) ){
str_part = "-";
}else {
if( i+1 < str.size() && str[i+1] != ')' && str[i+1] != '}' && str[i+1] != '!' )
putintoken(t,tok,'-');
}
}
}
//-------------------------------------------
// The multiplication symbol in the string
void Calculator::char_multiply( int i )
{
if( i+1 < str.size() && str[i+1] != ')' && str[i+1] != '}' && str[i+1] != '!' ){
if( str_part != " " )
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
if( i-1 >= 0 && str[i-1] != '(' && str[i-1] != '{' )
putintoken(t,tok,'*',0);
}
}
//-------------------------------------------
// The division symbol in the string
void Calculator::char_divide( int i )
{
if( i+1 < str.size() && str[i+1] != ')' && str[i+1] != '}' && str[i+1] != '!' ){
if( str_part != " " )
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
if( i-1 >= 0 && str[i-1] != '(' && str[i-1] != '{' )
putintoken(t,tok,'/');
}
}
//-------------------------------------------
// The percent symbol in the string
void Calculator::char_percent( int i )
{
if( i+1 < str.size() && str[i+1] != ')' && str[i+1] != '}' && str[i+1] != '!' ){
if( str_part != " " )
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
if( i-1 >= 0 && str[i-1] != '(' && str[i-1] != '{' )
putintoken(t,tok,'%');
}
}
//-------------------------------------------
// The exclamation symbol in the string
void Calculator::char_exclamation( int i )
{
if( i != 0 && i-1 >= 0 && ( str[i-1] == ')' || str[i-1] == '}' || str[i-1] == '!' ) ){
putintoken(t,tok,'!');
}else if( i != 0 && i-1 >= 0 && ((int(str[i-1]) >= 48 && int(str[i-1]) <= 57) || (int(str[i-1]) >= 65 && int(str[i-1]) <= 90) || (int(str[i-1]) >= 97 && int(str[i-1]) <= 122)) ){
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
putintoken(t,tok,'!');
}else throw errorfactorial();
}
//-------------------------------------------
// The opening parenthesis symbol in the string
void Calculator::char_roundbrace_open( int i, int &brace_open )
{
if( str_part != " " ){
if( variable_or_number() == true ){
putintoken(t,tok,variable);
if( tok[tok.size()-1].name != "sqrt" && tok[tok.size()-1].name != "pow" )
putintoken(t,tok,'*');
}else{
putintoken(t,tok,number);
putintoken(t,tok,'*');
}
}else if( i-1 >= 0 && ( str[i-1] == ')' || str[i-1] == '}' || str[i-1] == '!' ) )
putintoken(t,tok,'*');
putintoken(t,tok,'(', ++brace_open);
}
//-------------------------------------------
// The closing parenthesis symbol in the string
void Calculator::char_roundbrace_close( int i, int &brace_open, int &brace_close, vector<int> &brace_minusone )
{
if( str_part != " " ){
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
}
putintoken(t,tok, ')', brace_search(brace_open,')') );
++brace_close;
if( brace_minusone.size() > 0 && brace_minusone[brace_minusone.size()-1] == t.value-1 ){
putintoken(t,tok,')', brace_minusone[brace_minusone.size()-1]);
++brace_close;
brace_minusone.pop_back();
}
if( i+1 < str.size() && (( int(str[i+1]) >= 48 && int(str[i+1]) <= 57 ) || ( int(str[i+1]) >= 65 && int(str[i+1]) <= 90 ) || ( int(str[i+1]) >= 97 && int(str[i+1]) <= 122 )) )
putintoken(t,tok,'*');
}
//-------------------------------------------
// The opening curly braces symbol in the string
void Calculator::char_figurebrace_open( int i, int &figurebrace_open )
{
if( str_part != " " ){
if( variable_or_number() == true ){
putintoken(t,tok,variable);
if( tok[tok.size()-1].name != "sqrt" || tok[tok.size()-1].name != "pow" )
putintoken(t,tok,'*');
}else{
putintoken(t,tok,number);
putintoken(t,tok,'*');
}
}else if( i-1 >= 0 && ( str[i-1] == ')' || str[i-1] == '}' || str[i-1] == '!' ) )
putintoken(t,tok,'*');
putintoken(t,tok,'{', ++figurebrace_open);
}
//-------------------------------------------
// The closing curly braces symbol in the string
void Calculator::char_figurebrace_close( int i, int &figurebrace_open, int &figurebrace_close, int &brace_close, bool &figurebrace_minusone, vector<int> &brace_minusone )
{
if( str_part != " " ){
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
}
putintoken(t,tok,'}', brace_search(figurebrace_open, '{'));
++figurebrace_close;
if( figurebrace_minusone == true && brace_minusone.size() > 0 ){
putintoken(t,tok,')', brace_minusone[brace_minusone.size()-1]);
++brace_close;
brace_minusone.pop_back();
figurebrace_minusone = false;
}
if( i+1 < str.size() && (( int(str[i+1]) >= 48 && int(str[i+1]) <= 57 ) || ( int(str[i+1]) >= 65 && int(str[i+1]) <= 90 ) || ( int(str[i+1]) >= 97 && int(str[i+1]) <= 122 )) )
putintoken(t,tok,'*');
}
//-------------------------------------------
// The definition of the type of brackets
void Calculator::brace_definition( char bracevar, vector<char> &braces )
{
char br_open = '(';
char br_close = ')';
if( bracevar == '{' || bracevar == '}' ){
br_open = '{';
br_close = '}';
}else
if( bracevar == '[' || bracevar == ']' ){
br_open = '[';
br_close = ']';
}else
if( bracevar == '<' || bracevar == '>' ){
br_open = '<';
br_close = '>';
}
braces.push_back(br_open);
braces.push_back(br_close);
}
//-------------------------------------------
// Search the opening and closing brackets in the vector "tok"
int Calculator::brace_search( int brace_open, char bracevar )
{
vector<char> bracesvar;
brace_definition( bracevar, bracesvar );
char br_open = bracesvar[0];
char br_close = bracesvar[1];
for( int k = tok.size()-1 ; k >= 0 ; --k ){
if( tok[k].kind == br_open ){
break;
}else if( tok[k].kind == br_close ){
for( int m = k ; m >= 0 ; --m ){
if( tok[m].kind == br_close && tok[m].value == tok[k].value ){
--brace_open;
}
}
}
}
return brace_open;
}
//-------------------------------------------
// Separator for use in functions
void Calculator::char_separator( int i )
{
if( i-1 > 0 && i+1 < str.size() && str[i+1] != ')' && str[i+1] != '}' && str[i+1] != '!' ){
if( str_part != " " )
if( variable_or_number() == true )
putintoken(t,tok,variable);
else
putintoken(t,tok,number);
if( str[i-1] != '(' && str[i-1] != '{' )
putintoken(t,tok,',',0);
}
}
//-------------------------------------------
// The dot character in the string
void Calculator::char_point()
{
if( str_part == " " ) str_part = ".";
else str_part += '.';
}
//-------------------------------------------
// Number in the string
void Calculator::char_number( int i )
{
if( str_part == " " ) str_part = str[i];
else str_part += str[i];
}
//-------------------------------------------
// The transformation of the string
// that contains digits and the dot
// in a floating point number
double Calculator::strnum()
{
double n = 0;
int offset = 0;
bool point = false;
for( int i = 0 ; i < str_part.size() ; ++i ){
switch( str_part[i] ){
case '.':
offset = i;
point = true; break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
n = strnum_offset( n, (str_part[i] - '0'), i, point, offset ); break;
default:
break;
}
}
if( str_part[0] == '-' ) n *= -1;
return n;
}
//-------------------------------------------
// The displacement of the position of digits
// in a floating point number
double Calculator::strnum_offset( double n, int num, int i, bool point, int offset )
{
if( i == 0 ){
n = num;
}else{
if( point == false ){
n *= 10;
n += num;
}else if( point == true ){
double k = 1;
for( int m = 0; m < (i-offset); ++m ){
k *= 10;
}
n += num / k;
}
}
return n;
}
//-------------------------------------------
// The letter symbol in the string
void Calculator::char_letter( int i )
{
if( str_part == " " ) str_part = str[i];
else if( int(str_part[str_part.size()-1]) >= 48 && int(str_part[str_part.size()-1]) <= 57 ){
putintoken(t,tok,number);
putintoken(t,tok,'*');
str_part = " ";
str_part = str[i];
}
else str_part += str[i];
}
//-------------------------------------------
// The equal symbol in the string
void Calculator::char_equal( int i )
{
if( str[i] = '=' ){
for( int j = i+1 ; j < str.size() ; ++j ){
if( str[j] == '=' ) throw errorequalscorrect();
}
if( str_part != " " ){
if( variable_or_number() == true ) putintoken(t,tok,variable);
else putintoken(t,tok,number);
}
putintoken(t,tok,'=');
}
}
//-------------------------------------------
// Adding tokens without values in the vector "tok"
void Calculator::putintoken( Calculatortoken &t, vector<Calculatortoken> &tok, char ch )
{
if( ch == variable ){
t.kind = variable;
t.name = str_part;
t.value = vars.set_variable_value( str_part );
tok.push_back(t);
t.name = " ";
str_part = " ";
}else if( ch == number ){
t.kind = number;
t.value = strnum();
tok.push_back(t);
str_part = " ";
}else if( ch == '.' ){
t.kind = number;
t.value = strnum();
tok.push_back(t);
str_part = " ";
}else if( ch == '*' || ch == '/' || ch == '%' || ch == '!' ||
ch == '+' || ch == '-' ||
ch == '(' || ch == ')' ||
ch == '{' || ch == '}' ||
ch == '=' || ch == ',' ){
t.kind = ch;
t.value = 0;
tok.push_back(t);
str_part = " ";
}
}
//-------------------------------------------
// Adding tokens to the value in the vector "tok"
void Calculator::putintoken( Calculatortoken &t, vector<Calculatortoken> &tok, char ch, double n )
{
if( ch == variable ){
t.kind = variable;
t.name = str_part;
t.value = vars.set_variable_value( str_part, n );
tok.push_back(t);
t.name = " ";
str_part = " ";
}else if( ch == number ){
t.kind = number;
t.value = n;
tok.push_back(t);
str_part = " ";
}else if( ch == '.' ){
t.kind = number;
t.value = n;
tok.push_back(t);
str_part = " ";
}else if( ch == '*' || ch == '/' || ch == '%' || ch == '!' ||
ch == '+' || ch == '-' ||
ch == '(' || ch == ')' ||
ch == '{' || ch == '}' ||
ch == ',' ){
t.kind = ch;
t.value = n;
tok.push_back(t);
str_part = " ";
}
}
//-------------------------------------------
/********************************************
Erase tokens.
********************************************/
//-------------------------------------------
// Removing consecutive duplicated elements from a vector 'tok'
Calculator::tokenerase()
{
if( tok.size() > 1 ){
for( int i = 0 ; i < tok.size() ; ++i ){
if( tok[i].kind == number ){
if( i+1 < tok.size() && tok[i+1].kind == number && tok[i].value == tok[i+1].value ){
tok.erase(tok.begin()+i+1);
}
if( i-1 > 0 && tok[i-1].kind == number && tok[i].value == tok[i-1].value ){
tok.erase(tok.begin()+i-1);
}
}
}
}
}
//-------------------------------------------
// Remove values from a vector 'tok' after the operation of addition
Calculator::tokeneraseafteroperation( int &n, int ago, int forvard, int &tokbegin, int &tokbefor )
{
if( tok.size() > 1 && n-ago >= 0 && n+forvard < tok.size() ){
if( forvard > 0 ){
for( int i = n+1 ; i <= n+forvard ; ++i ){
tok.erase(tok.begin()+n+1);
--tokbefor;
}
}
if( ago > 0 ){
int nin = n;
for( int i = n-1 ; i >= nin-ago ; --i ){
tok.erase(tok.begin()+n-1);
--tokbegin;
--n;
}
}
}
}
//-------------------------------------------
/********************************************
Calculations.
********************************************/
//-------------------------------------------
// The feature that unites all the calculations
double Calculator::calculation()
{
double dbl = 0;
bool figurebrace = false;
bool brace = false;
bool operators = true;
int start = 0;
int finish = tok.size();
do{
dbl = calcoperation( dbl, operators );
figurebrace = braceconverce( '{' );
brace = braceconverce( '(' );
figurebrace = braceconverce( '{' );
brace = braceconverce( '(' );
dbl = calcoperation( dbl, operators );
}while( figurebrace == false || brace == false || operators == true );
dbl = equals( dbl );
return dbl;
}
//-------------------------------------------
// The calculation without brackets
double Calculator::calcoperation( double dbl, bool &operators )
{
dbl = variable_sqrt( dbl );
dbl = variable_pow( dbl );
dbl = calcoperationinbrace( dbl, '*', '(' );
dbl = calcoperationinbrace( dbl, '*', '({' );
dbl = calcoperationinbrace( dbl, '+', '(' );
dbl = calcoperationinbrace( dbl, '+', '({' );
dbl = factorial( dbl );
dbl = multiplication_and_division( dbl );
dbl = addition_and_subtraction( dbl );
tokenerase();
operators = false;
for( int i = 0 ; i < tok.size() ; ++i ){
if( tok[i].kind == '*' || tok[i].kind == '/' || tok[i].kind == '+' || tok[i].kind == '-' || tok[i].kind == '!' || tok[i].name == "sqrt" ){
operators = true;
}
}
return dbl;
}
//-------------------------------------------
// The calculation without brackets
double Calculator::calcoperationinbrace( double dbl, char sign, char bracevar )
{
vector<char> bracesvar;
brace_definition( bracevar, bracesvar );
char br_open = bracesvar[0];
char br_close = bracesvar[1];
for( int i = 0 ; i < tok.size() ; ++i ){
if( tok[i].kind == br_open ){
for( int j = i+1 ; j < tok.size() ; ++j ){
if( tok[j].kind == '(' || tok[j].kind == '{' ) break;
if( tok[j].kind == br_close ){
if( sign == '*' ) dbl = multiplication_and_division( dbl, i, j );
else
if( sign == '+' ) dbl = addition_and_subtraction( dbl, i, j );
braceconverce( '{' );
braceconverce( '(' );
}
}
}
}
return dbl;
}
//-------------------------------------------
bool Calculator::num_or_var( int n )
{
if( tok[n].kind == number || tok[n].kind == variable ) return true;
else return false;
}
bool Calculator::num_or_var( int n1, int n2 )
{
bool nv = false;
if( tok[n1].kind == number || tok[n1].kind == variable ) nv = true;
else nv = false;
if( tok[n2].kind == number || tok[n2].kind == variable ) nv = true;
else nv = false;
return nv;
}
bool Calculator::num_or_var( int n1, int n2, int n3 )
{
bool nv = false;
if( tok[n1].kind == number || tok[n1].kind == variable ) nv = true;
else nv = false;
if( tok[n2].kind == number || tok[n2].kind == variable ) nv = true;
else nv = false;
if( tok[n3].kind == number || tok[n3].kind == variable ) nv = true;
else nv = false;
return nv;
}
//-------------------------------------------
//bool Calculator::braceconverce( char bracevar, int &tokbegin, int &tokbefore )
bool Calculator::braceconverce( char bracevar )
{
vector<char> bracesvar;
brace_definition( bracevar, bracesvar );
char br_open = bracesvar[0];
char br_close = bracesvar[1];
for( int i = 0; i < tok.size(); ++i ){
if( tok[i].kind == br_open && i+1 < tok.size() && num_or_var(i+1) ){
for( int j = i; j < tok.size(); ++j ){
if( tok[j].kind == '*' || tok[j].kind == '/' || tok[j].kind == '+' || tok[j].kind == '-' || tok[j].kind == '%' || tok[j].kind == ',' ){
break;
}else if( tok[j].kind == br_close ){
tok.erase(tok.begin()+j);
tok.erase(tok.begin()+i);
break;
}
}
}
}
for( int i = 0; i < tok.size(); ++i ){
if( tok[i].kind == '(' || tok[i].kind == ')' || tok[i].kind == '{' || tok[i].kind == '}' )
return false;
}
return true;
}
//-------------------------------------------
// Calculation the square root
double Calculator::variable_sqrt( double dbl )
{
int k = 0;
for( int i = 0 ; i < tok.size(); ++i ){
if( tok[i].name == "sqrt" && num_or_var(i+1) ){
dbl = sqrt(tok[i+1].value);
tok[i].kind = number;
tok[i].value = dbl;
tok[i].name = " ";
tokeneraseafteroperation(i,0,1,k,k);
}
}
return dbl;
}
//-------------------------------------------
// Calculation pow()
double Calculator::variable_pow( double dbl )
{
int k = 0;
for( int i = 0 ; i < tok.size(); ++i ){
if(tok[i].name == "pow" &&
tok[i+1].kind == '(' &&
num_or_var(i+2) &&
tok[i+3].kind == ',' &&
num_or_var(i+4) &&
tok[i+5].kind == ')' ){
dbl = pow(tok[i+2].value,tok[i+4].value);
tok[i].kind = number;
tok[i].value = dbl;
tok[i].name = " ";
tokeneraseafteroperation(i,0,5,k,k);
}
}
return dbl;
}
//-------------------------------------------
// Multiplication and division
double Calculator::multiplication_and_division( double dbl )
{
int k = 0;
for( int i = 0; i < tok.size(); ++i ){
if ( tok[i].kind == '*' && num_or_var(i-1,i+1) ) {
dbl = tok[i-1].value * tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,k);
}else
if ( tok[i].kind == '/' && num_or_var(i-1,i+1) ) {
if( tok[i+1].value == 0 ) throw divisionbyzero();
dbl = tok[i-1].value / tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,k);
}else
if ( tok[i].kind == '%' && num_or_var(i-1,i+1) ) {
dbl = tok[i-1].value - tok[i+1].value * int(tok[i-1].value / tok[i+1].value);// if double number
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,k);
}
}
return dbl;
}
//-------------------------------------------
// Multiplication and division in a certain range of tokens vector
double Calculator::multiplication_and_division( double dbl, int &k, int &m )
{
for( int i = k; i < m; ++i ){
if( tok[i].kind == ')' || tok[i].kind == '}' ){
break;
}else
if( tok[i].kind == '*' && num_or_var(i-1,i+1) ){
dbl = tok[i-1].value * tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,m);
}else
if( tok[i].kind == '/' && num_or_var(i-1,i+1) ){
if( tok[i+1].value == 0 ) throw divisionbyzero();
dbl = tok[i-1].value / tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,m);
}else
if( tok[i].kind == '%' && num_or_var(i-1,i+1) ) {
dbl = tok[i-1].value - tok[i+1].value * int(tok[i-1].value / tok[i+1].value);
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,m);
}
}
return dbl;
}
//-------------------------------------------
// Addition and subtraction
double Calculator::addition_and_subtraction( double dbl )
{
int k = 0;
for( int i = 0; i < tok.size(); ++i ){
if ( tok[i].kind == '+' && num_or_var(i-1,i+1) ) {
dbl = tok[i-1].value + tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,k);
}else if( tok[i].kind == '-' && num_or_var(i-1,i+1) ) {
dbl = tok[i-1].value - tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,k);
}
}
return dbl;
}
//-------------------------------------------
// Addition and subtraction in a certain range of tokens vector
double Calculator::addition_and_subtraction( double dbl, int &k, int &m )
{
for( int i = k; i < m; ++i ){
if( tok[i].kind == ')' || tok[i].kind == '}' ){
break;
}else if( tok[i].kind == '+' && num_or_var(i-1,i+1) ) {
dbl = tok[i-1].value + tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,m);
}else if( tok[i].kind == '-' && num_or_var(i-1,i+1) ) {
dbl = tok[i-1].value - tok[i+1].value;
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,1,k,m);
}
}
return dbl;
}
//-------------------------------------------
// Factorial
double Calculator::factorial( double dbl )
{
int k = 0;
bool mins = false;
for( int i = 0 ; i < tok.size() ; ++i ){
if( tok[i].kind == '!' && i-1 >= 0 && num_or_var(i-1) ){
dbl = int(tok[i-1].value);
if( dbl == 0 ) dbl = 1;
else{
if ( dbl-1 < 0 ){
dbl *= -1;
mins = true;
}
for( int j = dbl-1; j >= 1; --j ){
dbl *= j;
}
if( mins == true ){
dbl *= -1;
mins = false;
}
}
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,0,k,k);
}
}
return dbl;
}
//-------------------------------------------
// Factorial in a certain range of tokens vector
double Calculator::factorial( double dbl, int &k, int &m )
{
bool mins = false;
for( int i = k ; i < m ; ++i ){
if( tok[i].kind == '!' && i-1 >= 0 && num_or_var(i-1) ){
dbl = int(tok[i-1].value);
if( dbl == 0 ) dbl = 1;
else{
if ( dbl-1 < 0 ){
dbl *= -1;
mins = true;
}
for( int j = dbl-1; j >= 1; --j ){
dbl *= j;
}
if( mins == true ){
dbl *= -1;
mins = false;
}
}
tok[i].kind = number;
tok[i].value = dbl;
tokeneraseafteroperation(i,1,0,k,m);
}
}
return dbl;
}
//-------------------------------------------
// Assignment operations
double Calculator::equals( double dbl )
{
int k = 0; int m = 0;
for( int i = 0 ; i < tok.size() ; ++i ){
if( tok[i].kind == '=' ){
if( i > 0 && i < tok.size()-1 ){
if( tok[i-1].kind == variable && tok[i-1].name != " " && num_or_var(i+1) ){
string snam = tok[i-1].name;
tok[i].kind = '8';
tok[i].name = " ";
tok[i].value = tok[i+1].value;
dbl = tok[i].value;
vars.var_table_push_back( tok[i-1].name, tok[i].value );
tokeneraseafteroperation(i,1,1,k,m);
}else if( tok[i-1].value == tok[i+1].value ){
tok[i].kind = '8';
tok[i].name = " ";
tok[i].value = tok[i+1].value;
dbl = tok[i+1].value;
tokeneraseafteroperation(i,1,1,k,m);
}
else {
throw errorequalscorrect();
}
}
}
}
return dbl;
}
//-------------------------------------------
/********************************************
Validation
********************************************/
//-------------------------------------------
// Determination of the correctness of operations
void Calculator::validationstrexpression()
{
bool operands = false;
bool operators = false;
bool twooperators = false;
bool emptybraces = false;
bool bracescorrect = false;
bool separatecorrect = true;
bool sqrtcorrect = true;
bool powcorrect = true;
int start = 0;
int finish = tok.size();
for( int i = 0; i < tok.size(); ++i ){
if( tok[i].kind == '8' ){
operands = true;
}else if( tok[i].name != " " ){
operands = true;
}else if( tok[i].kind == '!' ){
operators = true;
}else if( tok[i].kind == '*' || tok[i].kind == '/' || tok[i].kind == '+' || tok[i].kind == '-' || tok[i].kind == '%' || tok[i].kind == '=' ){
operators = true;
if( i+1 < tok.size() ){
if( tok[i+1].kind == '*' || tok[i+1].kind == '/' || tok[i+1].kind == '+' || tok[i+1].kind == '%' || tok[i+1].kind == '!' || tok[i+1].kind == '=' ){
twooperators = true;
}
}
}else if( tok[i].kind == '{' ){
if( i+1 < tok.size() ){
if( tok[i+1].kind == '}' ) emptybraces = true;
}
}else if( tok[i].kind == '(' ){
if( i+1 < tok.size() ){
if( tok[i+1].kind == ')' ) emptybraces = true;
}
}else if( tok[i].kind == ',' ){
operators = true;
start = 0;
finish = tok.size();
bracescorrect = bracecorrect( start, finish );
if( bracescorrect == true ){
start = 0;
finish = i-1;
bool bracescorrect1 = bracecorrect( start, finish );
start = i+1;
finish = tok.size();
bool bracescorrect2 = bracecorrect( start, finish );
if( bracescorrect1 == false && bracescorrect2 == false ){
for( int j = i-1 ; j >= 0 ; --j ){
if( tok[j].name == "pow" && tok[j+1].kind == '(' ){
separatecorrect = true;
powcorrect = true;
}
}
if( separatecorrect == false ){
powcorrect = false;
}
}else separatecorrect = false;
}else separatecorrect = false;
break;
}
if( tok[i].name == "sqrt" ){
if( i+3 < tok.size() && tok[i+1].kind == '(' ){
operators = true;
operands = true;
sqrtcorrect = true;
}else sqrtcorrect = false;
}else if( tok[i].name == "info" || tok[i].name == "help" ){
operators = true;
operands = true;
}
}
if( bracescorrect == false ){
start = 0;
finish = tok.size();
bracescorrect = bracecorrect( start, finish );
}
if( operands == false ) throw errornooperands();
if( operators == false ) throw errornooperators();
if( twooperators == true ) throw errortwooperatorsinarow();
if( emptybraces == true ) throw erroremptybraces();
if( separatecorrect == false ) throw errorseparatorcorrect();
if( bracescorrect == false ) throw errorbracecorrect();
if( sqrtcorrect == false ) throw errorsqrtcorrect();
if( powcorrect == false ) throw errorpowcorrect();
}
//-------------------------------------------
// The definition of the proper use of parentheses
bool Calculator::bracecorrect( int start, int finish )
{
int figurebrace_num = 0;
int brace_num = 0;
for( int i = start ; i < finish ; ++i ){
switch( tok[i].kind ){
case '{':
++figurebrace_num;
bracecorrectclose( i, '{' );
break;
case '(':
++brace_num;
bracecorrectclose( i, '(' );
break;
case '}':
--figurebrace_num;
break;
case ')':
--brace_num;
break;
default:
break;
}
}
if( figurebrace_num == 0 && brace_num == 0 ){
return true;
}else{
return false;
}
}
//-------------------------------------------
// Validation of closing brackets
void Calculator::bracecorrectclose( int i, char braceopenchar )
{
char braceclosechar;
int figurebrace_num = 0;
int brace_num = 0;
if( braceopenchar == '{' ){
braceclosechar = '}';
figurebrace_num = 1;
}else
if( braceopenchar == '(' ){
braceclosechar = ')';
brace_num = 1;
}
for( int j = i+1; j < tok.size(); ++j ){
if( tok[j].kind == braceclosechar && tok[j].value == tok[i].value ){
if( braceopenchar == '{' ) --figurebrace_num;
else if( braceopenchar == '(' ) --brace_num;
if( figurebrace_num != 0 || brace_num != 0 ){
throw errorbracecorrect();
}
break;
}else if( tok[j].kind == '(' ){
++brace_num;
}else if( tok[j].kind == ')' ){
--brace_num;
}else if( tok[j].kind == '{' ){
++figurebrace_num;
}else if( tok[j].kind == '}' ){
--figurebrace_num;
}
}
}
//-------------------------------------------
/********************************************
Debug.
The output information
on the screen.
********************************************/
//-------------------------------------------
// Display the contents of the vector with the tokens "tok" in an expression
void Calculator::coutkind( int i, double d )
{
if( tok[i].kind == '!' ){
cout << '\n' << tok[i-1].value << ' ' << tok[i].kind << " = " << d << '\n';
}else{
cout << '\n' << tok[i-1].value << ' ' << tok[i].kind << ' ' << tok[i+1].value << " = " << d << '\n';
}
}
//-------------------------------------------
// Display the contents of the vector with the tokens "tok"
void Calculator::strnum_cout()
{
cout << '\n';
for( int i = 0 ; i < tok.size() ; ++i ){
if( tok[i].value < 0 ) cout << ' ';
cout << tok[i].kind << ' ';
}
cout << '\n';
for( int i = 0 ; i < tok.size() ; ++i ){
cout << tok[i].value << ' ';
}
cout << '\n';
for( int i = 0 ; i < tok.size() ; ++i ){
cout << tok[i].name << ' ';
}
cout << '\n';
char che = ' ';
cin >> che;
}
//-------------------------------------------