Calculator Help!

Im trying to make a basic calculator that takes in an expression. Im not really sure where im going wrong so if someone could please take a look at my code and give a few suggestions.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <cctype>
#include <cstring>
#include <iostream>
#include <stack>
#include <cmath>
#include <math.h>
#include <cstdlib>
using namespace std;
bool precedence(stack<char>& operators);
double read_and_evaluate(string exp);
void evaluate_stack_tops(stack<double>& numbers, stack<char>& operators);
stack<double> numbers;
stack<char> operators;

int main(){
    double answer;
  
    string exp;
    cout << "Enter in an experssion: " << endl;
    cin >> exp;
    answer = read_and_evaluate(exp);
    cout << "That evaluates to: " << answer << endl;

    return 0;
}

bool precedence(char &a, char &b){
    b= operators.top();
    operators.pop();
    a=operators.top();
    
    if(b=='~')
        return false;
    else if(a=='(')
        return false;
    else if(a=='~')
        return true;
    else if(a=='$')
        return false;
    else if(b== '^')
        return false;
    else if(a== '+' || a=='-')
        return false;
    else if(b=='*' || b=='/' || b=='%')
        return false;
    else
        return true;
    
}

double read_and_evaluate (string exp){
            
    
    for(int i =0; i < exp.length(); i++){
        if(isdigit(exp[i])){
            
            numbers.push(exp[i]);
            cout << "these are the numbers being used: " << exp[i] << endl;
        }
        else if (exp[i] == '+'|| exp[i] == '*' || exp[i] == '/' || exp[i] == '%' || exp[i] == '^' << exp[i] == '('){
            operators.push(exp[i]);
            cout << "This is an operator : " << exp[i] << endl;
        }
        else if(exp[i] == '-'){
            
            if(exp[i-1] == '('){
                exp[i] = '~';
                cout << "This is an expression " << exp[i] << endl;
                operators.push(exp[i]);
            }
        
            else{
                cout << "this is an expression: " << exp[i] << endl;
           
                operators.push(exp[i]);
            }
        }
        else if(exp[i] == ')'){
        while(operators.top() !='(')
            evaluate_stack_tops(numbers, operators);
        }
            
    }
    return numbers.top();

}
void evaluate_stack_tops(stack<double>& numbers, stack<char>& operators){
    double num2;
    double num1;
    num2 = numbers.top();
    numbers.pop();
    num1 = numbers.top();
    numbers.pop();
    
    switch(operators.top()){
        case '+':
            numbers.push(num1+num2);
            break;
        case '-':          
            numbers.push(num1-num2);
            break;
        case '*':
            numbers.push(num1*num2);
            break;
        case '/':
            numbers.push(num1/num2);
            break;
        case '^':
            numbers.push(pow(num1,num2));
            break;
        case '%':                          
            numbers.push(fmod(num1,num2));
            break;
        case '~':                          
            numbers.push(num2 * -1);
            break;

    }
    operators.pop();
    
}
Without looking too hard at your code, I think the main problem is that you're not taking precedence into consideration when pushing operators into your stack. Regardless of the particular operators in an expression, the program will always apply them in the same order. The end result being that 1+2*3 ≠ 2*3+1.
Another subtlety is that ^ typically associates to the right. Meaning a^b^c == a^(b^c).

precedence() doesn't make much sense to me.

There's a stray << on line 60.
Your right final example output?
(Your code is too hard to read.)
I was just trying to get it to do a basic expression first like (3+4) but it wasnt working so i decided to comment all of that out until i figured out the rest. I have found out that i need to convert my exp to double using strtod().
It will be better to use if else loop then switch case. Your code makes confused. I do not have a mean "precedence" ?
really it is so confusing.. Change the codes...
@OP : Your code style :

if(b=='~')
return false;
else if(a=='(')
return false;
else if(a=='~')
return true;
else if(a=='$')
return false;
else if(b== '^')
return false;
else if(a== '+' || a=='-')
return false;
else if(b=='*' || b=='/' || b=='%')
return false;
else
return true;


Could be changed to :
1
2
3
4
5
6
7
8
9
10
 
    if(b == ' ~ ')return false;
    if(a == ' ( ')return false;
    if(a == ' $ ')return false;
    if(b == ' ^ ')return false;

    if(a == ' + ' || a == ' - ')return false;
    if(b == ' * ' || b == ' / ' || b == ' % ')return false;

    return true;

Each comparison expression has a "return" command, so no need to add "else"... This make your code harder to read - understand...
Last edited on
switch(operators.top()){
case '+':
numbers.push(num1+num2);
break;
case '-':
numbers.push(num1-num2);
break;
case '*':
numbers.push(num1*num2);
break;
case '/':
numbers.push(num1/num2);
break;
case '^':
numbers.push(pow(num1,num2));
break;
case '%':
numbers.push(fmod(num1,num2));
break;
case '~':
numbers.push(num2 * -1);
break;
}


1
2
3
4
5
6
7
8
9
10
11
 switch(operators.top()){
        case '+': numbers.push(num1 + num2);break;
        case '-': numbers.push(num1 - num2);break;
        case '*': numbers.push(num1 * num2);break;
        case '/': numbers.push(num1 / num2);break;

        case '^': numbers.push(pow(num1,num2));break;
        case '%': numbers.push(fmod(num1,num2));break;
        case '~': numbers.push(num2 * -1);break;
            
}
@Jackson Marie - It's not good practice to have >1 return expression. Much better to declare a return variable of the correct type and set that in your code. Neither will your variables compare if you have spaces:

1
2
char b = 'b';
if (b == ' b ')


the above will evaluate to false not true as you expect.

if(b == ' ~ ')return false;
if(a == ' ( ')return false;
if(a == ' $ ')return false;
if(b == ' ^ ')return false;

if(a == ' + ' || a == ' - ')return false;
if(b == ' * ' || b == ' / ' || b == ' % ')return false;

return true;




1
2
3
4
5
6
    

    if(a == '+' || a == '-'|| a == '(' || a == '$')return false;
    if(b == '*' || b == '/' || b == '%' || b == '~' || b == '^')return false;

    return true;
Last edited on
Topic archived. No new replies allowed.