Skip to content

Calc#9

Open
ratneshkatiyar wants to merge 7 commits intoalexkutsan:masterfrom
ratneshkatiyar:Calculator
Open

Calc#9
ratneshkatiyar wants to merge 7 commits intoalexkutsan:masterfrom
ratneshkatiyar:Calculator

Conversation

@ratneshkatiyar
Copy link
Copy Markdown

No description provided.

{
EXPECT_EQ(7.8, project_.calc("5.5 2.3 +"));
}
TEST_F(CalculatorTest, MissingOperand)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Negative and positive test cases.

}
TEST_F(CalculatorTest, MissingOperand)
{
EXPECT_EQ(-1, project_.calc("5 +"));
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check a way to handle errors

if (str.size() == 0)
return 0;
throw Exception{"Nothing to work on as Input is empty"};
for (int i = 0; i < str.size(); i++)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to use iterator or range based loop?

// {
// std::cout << "calc::Exception" << e.what();
// }
res = performOperation(str[i], operandVal.first, operandVal.second);
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next step is to separate parsing and evaluating

return mStack.top();
}

void PolishCalc::pushOperandInStack(const std::string &str, int &curr_pos)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. mark variable as output explicit with name curr_pos_out
  2. return new position

{
double secOperand = 0;
double firstOperand = 0;
if (mStack.size() >= 2)
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swap if condition and make early return/ throw ( safety check)

void pushOperandInStack(const std::string &, int &curr_pos);
std::pair<double, double> getOperandFromStack();
std::stack<double> mStack;
std::map<const char, functionCall> mMap;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mMap bad name. Try to avoid put type name in variable, Show business value of variable

double performOperation(const char operation, const double firstOperand, const double secOperand);
void pushOperandInStack(const std::string &, int& curr_pos);
std::pair<double,double> getOperandFromStack();
void insertFunctionInsideMap();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to use constexpr for this.

auto operandVal = getOperandFromStack();
double res = 0;
res = performOperation(str[i], operandVal.first, operandVal.second);
res = mMap[str[i]](operandVal.first, operandVal.second);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extract variable for str[i]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest to split implementation to parsing, validating and calculating steps

mMap.insert(std::make_pair('-', [](double a, double b) { return a - b; }));
mMap.insert(std::make_pair('*', [](double a, double b) { return a * b; }));
mMap.insert(std::make_pair('/', [](double a, double b) {
if(b==0)
Copy link
Copy Markdown
Contributor

@LuxoftAKutsan LuxoftAKutsan Jul 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if(0=b)

{
mMap.insert(std::make_pair('+', [](double a, double b) { return a + b; }));
mMap.insert(std::make_pair('-', [](double a, double b) { return a - b; }));
mMap.insert(std::make_pair('*', [](double a, double b) { return a * b; }));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use const as wide as you cat

throw Exception{"Nothing to work on as Input is empty"};
for (int i = 0; i < str.size(); i++)
{
if (str[i] == ' ')
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid missing brackets even in one line if/else/while ...

return false;
}

double PolishCalc::calc( const std::string &str)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 blocks :

1. Basic Validation // Check that the is not bad symbols and so on
2. Parsing // Use not strings, but OOP types or lambdas for futher working 
2.1 Validation : count of operator matches count of operands 
3. Calculation // Evaluete expression 

2 stacks :
Validation block fill up 2 stacks :

  1. Operator stack
  2. Operand stack

Calculation should work with Operator/Operand or lambda types but not string.

{
if (str[i] == ' ')
continue;
if (isNumeric(str[i]))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to modify solution to work with negative numbers

{
double operand = 0;
std::string temp = "";
while (curr_pos < str.size() && !(str[curr_pos] == ' '))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of input like 2 4+ , solution behaviour is undefined.
Try to handle this error.
Best option is to create prevalidation function and contract for pushOperandInStack.

continue;
if (isNumeric(str[i]))
{
pushOperandInStack(str, i);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to work with some kind of tokens but not charters.
It is not obvious that pushOperandInStack will modify i variable. If it is possible. Try to avoid it

pushOperandInStack(str, i);

}
if (isOperator(str[i]))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create separate loop to fill operator stack, operand stack an calculation based on 2 stacks

{
auto operandVal = getOperandFromStack();
double res = 0;
res = mOperatorMap[str[i]](operandVal.first, operandVal.second);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move calculation to the third loop

if (num == '+' || num == '-' || num == '*' || num == '/')
return true;
return false;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for (from 0 to N) { 
 Operation 1
 Operation 2
 Operation 3
}
for (from 0 to N) { 
 Opertation 1
}
for (from 0 to N) { 
 Opertation 2
}
for (from 0 to N) { 
 Opertation 3
}

Both solutions have the same performance

{
insertFunctionInsideMap();
}

Copy link
Copy Markdown
Contributor

@LuxoftAKutsan LuxoftAKutsan Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 Step : Create Token stack and validate it

token_stack& =  stack<Tocken>

Token {
  // Process one tocken in the stack 
    void process(token_stack& ) 
    double value(const token_stack& )  << // Follow contant 
}

NumericToken  : Token {
  void  process(token_stack& ) -> do nothing
  double  value(token_stack& ) -> return value_
  double value_
} 

OperatorTocken : Token {
  pair PopTockens 
}

PlusTocken  : OperatorTocken {
  void  process(token_stack& ) { 
     pop token from stack -> get value -> double res1
     pop token2 from stack -> get value -> double res2
     res1 + res2 -> Plus result 
     Push plus result to token vector  as Numeric 
  }
  
  double  value(const token_stack&) {
    // Option 1 Contract thet process() should be evaluated before value ()
     return top of the token_stack& value() 
  
    // Option 2 Base that there process() could not be called
         get token from stack -> get value -> double res1
         get token2 from stack on the second position -> get value -> double res2 
         res1 + res2 -> Plus result 
         return Plus result  as double 
  } 
} 

3 step Go throw all tokens and call process to them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants