# Need some help for calc code

Discussion in 'C++' started by gabuchia, Oct 8, 2009.

1. ### gabuchiaNew Member

Joined:
Oct 4, 2009
Messages:
11
0
Trophy Points:
0
, so I have this calc code, its accepts strings then calculates it. Can anyone explain what does the function. I can understand the bool check function though!

double value_of_num(const string &Expr) and double Value_Of_Expr(const string &Expr)

Code:
```class Calculator : protected base
{
enum {PLUS='+',MINUS='-',MUL='*',DIV='/'}; // Enumeration declaration : User defined type of a set of constants called enumerators
int precision;
double Value_Of_Num(const string &Expr)

{
istringstream is(Expr);
double value=0.0;
is >> value;
cout << setprecision(precision) << value;
}

double Value_Of_Expr(const string &Expr)

{
int i=0,p=0,pos_mul=0,pos_div=0;

if(Expr.at(0)=='('&&Expr.at(Expr.length()-1)==')')
{
for(i=0;i < Expr.length();i++)
{

if(Expr.at(i)=='(') p++;
else if(Expr.at(i)==')') p--;
if(p==0) break;

}

if(i==Expr.length()-1)
return Value_Of_Expr(Expr.substr(1,Expr.length()-2));
}

for(i=0;i < Expr.length();i++)
{
if(Expr.at(i)=='(') p++;
else if(Expr.at(i)==')') p--;
else if(p==0&&ispunct(Expr.at(i)))
{

switch(Expr.at(i))
{
case PLUS:
return Value_Of_Expr(Expr.substr(0,i))+Value_Of_Expr(Expr.substr(i+1,Expr.length()-i-1));
case MINUS:
return Value_Of_Expr(Expr.substr(0,i))-Value_Of_Expr(Expr.substr(i+1,Expr.length()-i-1));
case MUL: pos_mul=i;
break;
case DIV: pos_div=i;
break;

}
}
}

if(pos_mul)
return Value_Of_Expr(Expr.substr(0,pos_mul))*Value_Of_Expr(Expr.substr(pos_mul+1,Expr.length()-pos_mul-1));

if(pos_div)
return Value_Of_Expr(Expr.substr(0,pos_div))/Value_Of_Expr(Expr.substr(pos_div+1,Expr.length()-pos_div-1));

return Value_Of_Num(Expr);
}

// several important validation checks on the input
bool Check(string input_string)
{
// Checks for repeated usage of '+', '-', '*', '/' operators
for (int r = 0; r < input_string.length(); r++)
{
if((input_string[r]=='+')||(input_string[r]=='-')||(input_string[r]=='*')||(input_string[r]=='/'))
{
if((input_string[r+1]=='+')||(input_string[r+1]=='-')||(input_string[r+1]=='*')||(input_string[r+1]=='/'))
{
return false;
}
}
}
// Checks for the last character of the string equation
int g = input_string.length() ;
if(input_string[g-1] == '*' || input_string[g-1] =='/' || input_string[g-1] == '-' || input_string[g-1] == '+')
{
return false;
}
string array="0123456789+-*/()";
int count=0;
for (int s=0; s < input_string.length(); s++)
{
for(int z=0; z < array.length(); z++)
{
//Compares each number/operator with elements from 'array'
if(input_string[s]==array[z])
{
count++;
}
}
}
//every number/operator approved should be equals to input
if (count == input_string.length())
{
return true;
}
else
{
return false;
}
}
public :
Calculator()
{
string expression;

system("CLS");
cout << "                   Welcome to the calculator function!" << endl;
cout << "" << endl;
cout << "" << endl;
cout << "With this calculator, your problem solving is made simple." << endl;
cout << "You do not have to calculate each part of an expression one at a time \n";
cout << "like you do with you simple calculators." << endl;
cout << "All you have to do is simply input an expression \n";
cout << "and the calculator will give you the answer." << endl;

cout << "" << endl;
cin >> expression;
cout << "How many decimal places would you want your answer to be in?" << endl;
cin >> precision;
if(Check(expression)==true)
{
cout << Value_Of_Expr(expression)<<endl;
}
else
{
cout << "" <<endl;
cout << "Error in the input" << endl;
}
cout << endl << endl << endl;
Calculator_1:
base calculator1;
calculator1.display();

}
};```

2. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,009
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
It's unlikely anyone will give you a line by line breakdown of the entire function. What precisely do you want to know? Have you tried asking the person who wrote the code?

3. ### gabuchiaNew Member

Joined:
Oct 4, 2009
Messages:
11
0
Trophy Points:
0
Sadly, the author of this code did not leave his contact email. =(

double Value_Of_Num(const string &Expr)

this function is the one that's making my head spin, its only 4 lines long, thanks in advance for explaining!

4. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,009
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
As the name suggests it gets the value of a number. So for "27" it would return 27.

5. ### gabuchiaNew Member

Joined:
Oct 4, 2009
Messages:
11
0
Trophy Points:
0
My question will be, why does it need to create an object 'is' with istringstream.

And what does this line mean

Code:
`is >> value;`

6. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,009
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
Presumably because istringstream implements a conversion to double, whereas string doesn't. So you convert the string Expr to an istringstream with "istringstream is(Expr)", then invoke istringstream:perator>>(double), which performs the conversion, with "is >> value".

7. ### gabuchiaNew Member

Joined:
Oct 4, 2009
Messages:
11
0
Trophy Points:
0
So you're saying its essentially converting the value of Expr into an istringstream. Then it converts the 'is' which is created by the string 'Expr' and in the line of the code

Code:
`is >> value`
it converts 'is' into a double because value is declared as a double type data. Am I getting this right?

8. ### gabuchiaNew Member

Joined:
Oct 4, 2009
Messages:
11
0
Trophy Points:
0
As pointed by my friend, we noticed that the calculator does not take in negative numbers, is there any code that I should change to let it accept negative numbers?

ie :
(5*5)-(2*2)*-5

9. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,009
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
The code currently treats consecutive operators an error, so 3+-5 would throw an error because of the +-. It would need to be modified to throw an error only when this doesn't make sense, so for example 3+-5 is fine because it means three plus (-5), but 3+*5 would still throw an error.

Have a look at the code after the comment "// several important validation checks on the input"

10. ### gabuchiaNew Member

Joined:
Oct 4, 2009
Messages:
11
0
Trophy Points:
0
I have changed several codes of it, but it still wouldn't take a negative number. Here is the code, can you give me some suggestions?

Code:
```class Calculator : protected base
{
enum {PLUS='+',MINUS='-',MUL='*',DIV='/'};
int precision;
double Value_Of_Num(const string &Expr)

{
istringstream is(Expr);
double value;
is >> value;
return value;
}
double Value_Of_Expr(const string &Expr)

{
int i=0,p=0,pos_mul=0,pos_div=0;

if(Expr.at(0)=='('&&Expr.at(Expr.length()-1)==')')
{
for(i=0;i < Expr.length();i++)
{

if(Expr.at(i)=='(') p++;
else if(Expr.at(i)==')') p--;
if(p==0) break;

}

if(i==Expr.length()-1)
return Value_Of_Expr(Expr.substr(1,Expr.length()-2));
}

for(i=0;i < Expr.length();i++)
{
if(Expr.at(i)=='(') p++;
else if(Expr.at(i)==')') p--;
else if(p==0&&ispunct(Expr.at(i)))
{

switch(Expr.at(i))
{
case PLUS:
return Value_Of_Expr(Expr.substr(0,i))+Value_Of_Expr(Expr.substr(i+1,Expr.length()-i-1));
case MINUS:
return Value_Of_Expr(Expr.substr(0,i))-Value_Of_Expr(Expr.substr(i+1,Expr.length()-i-1));
case MUL: pos_mul=i; break;
case DIV: pos_div=i; break;

}
}
}

if(pos_mul)
return Value_Of_Expr(Expr.substr(0,pos_mul))*Value_Of_Expr(Expr.substr(pos_mul+1,Expr.length()-pos_mul-1));

if(pos_div)
return Value_Of_Expr(Expr.substr(0,pos_div))/Value_Of_Expr(Expr.substr(pos_div+1,Expr.length()-pos_div-1));

return Value_Of_Num(Expr);
}

// several important validation checks on the input
bool Check(string input_string)
{

for (int r = 0; r <= input_string.length(); r++)
{
if((input_string[r]=='+')||(input_string[r]=='-'))
{
if((input_string[r+1]=='+')||(input_string[r+1]=='-')||(input_string[r+1]=='*')||(input_string[r+1]=='/'))
{
return false;
}
}
}
for (int r = 0; r <= input_string.length(); r++)
{
if((input_string[r]=='*')||(input_string[r]=='/'))
{
if((input_string[r+1]=='*')||(input_string[r+1]=='/'))
{
return false;
}
}
}
string array="0123456789+-*/().";
int count=0;
for (int s=0; s < input_string.length(); s++)
{
for(int z=0; z < array.length(); z++)
{
if(input_string[s]==array[z])
{
count++;
}
}
}
if (count == input_string.length())
{
if(input_string.at(0) != '*' && input_string.at(0) != '/' && input_string.at(0) != '+' && input_string.at(0) != '-')
{
if(input_string.at(input_string.length()-1) != '*' && input_string.at(input_string.length()-1) != '/' && input_string.at(input_string.length()-1) != '+' && input_string.at(input_string.length()-1) != '-')
{
return true;
}
}
}
else
{
return false;
}
}
public :
Calculator()
{
string expression, choice;

system("CLS");
system("COLOR 03");
cout << "\t\t\tWelcome to the calculator function!" << endl;
cout << "" << endl;
cout << "" << endl;
cout << "With this calculator, your problem solving is made simple." << endl;
cout << "You do not have to calculate each part of an expression one at a time \n";
cout << "like you do with you simple calculators." << endl;
cout << "All you have to do is simply input an expression \n";
cout << "and the calculator will give you the answer." << endl;
cout << "" << endl;
cin >> expression;
if(Check(expression)==true)
{
cout << "Does your expression require precision of significant figures?[y/n]: ";
cin >> choice;
cout << endl;
if(choice == "y" || choice == "Y")
{
cout << "How many significant figures do you want it to display?" << endl;
cin >> precision;
cout << setprecision(precision) << Value_Of_Expr(expression)<<endl;
}
else
{
cout << "The answer is: ";
cout << Value_Of_Expr(expression)<<endl;
}
}
else
{
cout << "\a" <<endl;
cout << "Error in the input" << endl;
}
cout << endl << endl << endl;
base calculator1;
calculator1.display();

}
};```

11. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,009
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
Well the code still does this so I'm not surprised it doesn't accept negative numbers:
Code:
```                if((input_string[r]=='+')||(input_string[r]=='-'))
{
if((input_string[r+1]=='+')||(input_string[r+1]=='-')||(input_string[r+1]=='*')||(input_string[r+1]=='/'))
{
return false;
```
because this specifically excludes something like "3+-5".

Expression evaluation code is not in general simple to write, and more difficult to read and modify particularly when the code has as few comments as yours does. So I can't really make any suggestions except that you think carefully through what it is supposed to do, with pen and paper away from the computer. Decide on an initial algorithm, write several expressions out and work through that algorithm as the computer would: character by character, keeping track of variable contents, and following the algorithm strictly, being careful to do *exactly* what the algorithm states and NOT what you think it means. This isn't easy, and perhaps it would be helpful to talk through it with someone who can point out when you're doing what you meant rather than what you have written down.

You can then use that process to modify the algorithm so that it works with the example expressions you've thought up.

This is called a "dry run" and is a VERY important skill that all programmers *need*.

12. ### gabuchiaNew Member

Joined:
Oct 4, 2009
Messages:
11
0
Trophy Points:
0
If I were to remove the checking of 5--5, it would give me an error, if I enter that expression. Runtime error to be precise, any other suggestions?

13. ### xpi0t0sMentor

Joined:
Aug 6, 2004
Messages:
3,009
203
Trophy Points:
63
Occupation:
Senior Support Engineer
Location:
England
Solving this is not going to be as simplistic as just removing a bit of code. This is a complex project and you NEED to study what I suggested in my last post. If you don't want to do that then this project is beyond your abilities and you should look for something simpler.