# simple calculator

• 08-11-2005
Micko
simple calculator
I'm writing a simple calculator program. At first I wrote program that converts infix to postfix notation and I thought it would be simple thing to evaluate exression. This calculator is working with integers numbers only for the start. However I have a bug, for example -2*4-5 will not work because of the way of string processing I've chosen. That charatcer '-' is converted to some number. I would like you to aks for help, to give me advice how to change string processing, or maybe to start writing program from the scratch. I omitted error checking for simplicity.
Can you suggest me the way to fix this without large program modifications? It seems that this idea is not very useful. how would you approach to this problem?

Thank you very much

Code:

```#include <iostream> #include <string> #include <algorithm> #include <cctype> #include <stack> #include <cstdlib> #include <cmath> using namespace std; inline bool is_whitespace (const char&); inline bool is_operator (const char&); inline bool is_operand (const char&); inline bool higher_priority (const char&, const char&); inline bool same_priority (const char&, const char&); int get_priority (const char&); string remove_whtsp (string&);//remove whitespace characters string convert_to_postfix (string&); long postfix_eval (string&); int main() {         string a;         getline (cin, a);         string b = remove_whtsp (a);         string c = convert_to_postfix (b);         cout << (c)<<endl;         cout << postfix_eval(c);         return 0; } bool is_whitespace(const char& ch) {         return (isspace(ch) != 0); } bool is_operator (const char& ch) {         return (ch == '+' || ch == '*' || ch == '/' || ch == '-' || ch == '^'); } bool is_operand (const char& ch) {         return (isdigit(ch) != 0 || isalpha(ch) != 0); } bool higher_priority (const char& ch, const char& top) {         return get_priority(ch) > get_priority(top); } inline bool same_priority (const char& ch, const char& top) {         return get_priority (ch) == get_priority (top); } int get_priority (const char& ch) {         if (ch == '^') return 3;         else if (ch == '*' || ch == '/') return 2;         else if (ch == '+' || ch == '-') return 1;         else return 0; } string remove_whtsp (string& a) {         string b;         remove_copy_if(a.begin(), a.end(), back_inserter(b), is_whitespace);         return b; } string convert_to_postfix (string& str_infix) {         stack <char> st;         string str_postfix;         string :: const_iterator it;         it = str_infix.begin();         //step1. Examine the next element in the input.         while (it != str_infix.end())         {                 if (is_operand(*it))                 {                         str_postfix.push_back(*it);//step 2. If it is an operand, output it.                 }                 else if (*it == '(')                 {                         st.push(*it);//step 3. If it is opening parenthesis, push it on stack.                 }                 else if (is_operator(*it))//step4. If it is an operator, then                 {                         if (st.empty())                         {                                 st.push(*it);                         }                         else if (same_priority(st.top(), *it))                         {                                 str_postfix.push_back(st.top());                                 st.pop();                                 st.push(*it);                         }                         else if (higher_priority(*it, st.top()))                         {                                 st.push(*it);                         }                         else                         {                                 while (!higher_priority(*it, st.top()))                                 {                                         str_postfix.push_back(st.top());                                         st.pop();                                 }                                 st.push(*it);                         }                 }//end step 4.                 if (*it == ')')//step 5.If it is a closing parenthesis, //pop operators from the stack and output them until an opening parenthesis is encountered                 {                         while (st.top() != '(')                         {                                         str_postfix.push_back(st.top());                                         st.pop();                         }                         st.pop();                 }                 ++it;         }         while (!st.empty())//step7. If there is no more input, unstack the remaining operators to output.         {                 str_postfix.push_back (st.top());                 st.pop();         }         return str_postfix; } long postfix_eval(string& str) {         string tmp;         string :: const_iterator it;         stack <long> st;         long temp1, temp2;         for (it = str.begin(); it != str.end(); ++it)         {                 if (is_operand(*it))                 {                         tmp = *it;                         st.push(atol(tmp.c_str()));                         tmp = "";                 }                 else if (is_operator(*it))                 {                         temp1 = st.top();                         st.pop();                         temp2 = st.top();                         st.pop();                         if (*it == '+')                         {                                 st.push(temp1 + temp2);                         }                         else if(*it == '-')                         {                                 st.push(temp2 - temp1);                         }                         else if(*it == '*')                         {                                 st.push(temp1 * temp2);                         }                         else if(*it == '/')                         {                                 st.push(temp2 / temp1);                         }                         else if (*it == '^')                         {                                 st.push(static_cast<long>(pow(temp2, temp1)));//I had to do casting                         }                 }         }         temp1 = st.top();         st.pop();         return temp1; }```
- Micko
• 08-11-2005
orbitz
This is probably not what you want to hear but the easiest way to do this would probably be using lex & yacc. You can define a grammar which tokenises the integers and operators and gives you a tree structure. After that you just iterate through the tree and evaluate the expressions.
I have not done this myself in lex & yacc but I have written the basic grammar in yecc:
Code:

```Nonterminals expr statement function params.                                                                                                                                                                                                                                                                                                                                                                                    Terminals 'integer' 'var' '+' '-' '*' '/' '(' ')' '=' ',' 'and' 'or' '=='.                                                                                                                                                                                                                                                                                                                                                      Rootsymbol statement.                                                                                                                                                                                                                                                                                                                                                                                                            Left 100 '+'.                                                                                                                                                                                                    Left 100 '-'.                                                                                                                                                                                                    Left 100 'or'.                                                                                                                                                                                                  Left 200 '*'.                                                                                                                                                                                                    Left 200 '/'.                                                                                                                                                                                                    Left 200 'and'.                                                                                                                                                                                                  Unary 600 '-'.                                                                                                                                                                                                  Unary 600 '+'.                                                                                                                                                                                                                                                                                                                                                                                                                  statement -> statement ',' statement : {sequence, '\$1', '\$3'}.                                                                                                                                                  statement -> expr : '\$1'.                                                                                                                                                                                        statement -> function : '\$1'.                                                                                                                                                                                                                                                                                                                                                                                                    expr -> expr '+' expr : {add, '\$1', '\$3'}.                                                                                                                                                                      expr -> expr '-' expr : {subtract, '\$1', '\$3'}.                                                                                                                                                                  expr -> expr '*' expr : {multiply, '\$1', '\$3'}.                                                                                                                                                                  expr -> expr '/' expr : {divide, '\$1', '\$3'}.                                                                                                                                                                    expr -> expr 'and' expr : {land, '\$1', '\$3'}.                                                                                                                                                                    expr -> expr 'or' expr : {lor, '\$1', '\$3'}.                                                                                                                                                                      expr -> expr '==' expr : {eq, '\$1', '\$3'}.                                                                                                                                                                      expr -> '(' expr ')' : '\$2'.                                                                                                                                                                                    expr -> '-' expr : {negative, '\$2'}.                                                                                                                                                                            expr -> '+' expr : {positive, '\$2'}.                                                                                                                                                                            expr -> 'integer' : '\$1'.                                                                                                                                                                                        expr -> 'var' '(' params ')' : {funccall, '\$1', '\$3'}.                                                                                                                                                          expr -> 'var' '(' ')' : {funccall, '\$1', nil}                                                                                                                                                                    expr -> 'var' : {funccall, '\$1', nil}.                                                                                                                                                                                                                                                                                                                                                                                          function -> 'var' '(' params ')' '=' expr : {funcdef, '\$1', '\$3', '\$6'}.                                                                                                                                        function -> 'var' '(' ')' '=' expr : {funcdef, '\$1', nil, '\$5'}.                                                                                                                                                                                                                                                                                                                                                                params -> 'var' ',' params : {param, '\$1', '\$3'}.                                                                                                                                                                params -> 'var' : {param, '\$1', nil}.```
That is a bit more complex and allows you to do assignment. However this is just a starting point and probably more than what you want.
To actually answer the question you asked:
A good idea would probably be to, isntead of making a new postfix string, create a tree which represents the expression and then recurse through the tree to evaluate. In order to evaluate the string you should write a finite state machine. This means instead of looking for an operator such as '-' or '+', and assuming it's a binary operator you figure out what it should be based on the current state and the input token. So for instance to evaluate "-2" you would first probably wan tot break it up into tokens, in this case you have '-' being an operator, then '2' being a number. Then you evaluate this data with a fsm. you have an initial state, you see the '-' operator, and decide wether to reduce or shift, move onto a new state, see the '2' and decide to reduce or shift.
I think that, if anything, I have just made your much more confused about what is going on but perhaps I have given you some good google search terms. If you ask some more questions I'll try to take the time to give you more useful and coherent answers.
Sorry
• 08-11-2005
ILoveVectors
you are already using string maybe stringstream could
• 08-12-2005
treenef
Yeah probably use a binary tree or linked list of some sort. Since the fundamental properties of a binary tree make it ideal for dealing with basic arithmetic or algebra .

For example, since multiplication has priority over the other operators it would occupy the root node in the binary tree. The other operators, such as '+' and '-' would be positioned below the '*' and '/' . Then it would be a case of recursively evaluating
each expression as you traverse through the tree. (what orbitz said me thinks).

The link below should give you some practical ideas where and how to approach this.

http://cboard.cprogramming.com/showt...algebra+solver
• 08-12-2005
Micko
Thanks for replies, I'll be very busy next week, but after that I'll be back (hopefuly) with solution or with further questions.

- Micko