smart calculator

I made a calculator that you can type in a expression and it will figure out the operator and numbers and calculates it. well I got it to work but then i wanted it to work with decimals, then work with multiple operators. but the ispunct function doesn't seem to work right for the decimal point. Let me know if you have any suggestions for either addition.

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
122
123
124
125
126
#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;

int main()
{
    string Input;
    string NumBeforeOp;
    string NumAfterOp;
    string OpResult = "";
    int Counter = 0;
    int NumOne = 0;
    int NumTwo = 0;
    int Answer = 0;
    bool FoundAdd = false;
    bool FoundSub = false;
    bool FoundMul = false;
    bool FoundDiv = false;

    cout << "Using + for add, - for subtraction, * for multiplying, and / for divide," << endl;
    cout << "enter an arithmetic expression to calculate:" << endl;
    getline(cin, Input); //get input

    cout << endl;
    cout << "Detecting your operator..." << endl;

    while(Counter != Input.size())//look for an operator
    {
        if(Input[Counter] == '+')
        {
            FoundAdd = true;
            OpResult = "Additon";
        }

        if(Input[Counter] == '-')
        {
            FoundSub = true;
            OpResult = "Subtraction";
        }

        if(Input[Counter] == '*')
        {
            FoundMul = true;
            OpResult = "Multiplication";
        }

        if(Input[Counter] == '/')
        {
            FoundDiv = true;
            OpResult = "Division";
        }

        Counter++;
    }

    Counter = 0; //reset the counter

    if((FoundAdd == true)||(FoundSub == true)||(FoundMul == true)||(FoundDiv == true))
    {
        cout << "Detected " << OpResult << "!" << endl; //output what operator it found
    }

    else
    {
        cout << "Operation not found. Exiting program..." << endl; //exit if theres no operator
        return 0;
    }

    cin.get();

    cout << "Detecting numbers before the operator..." << endl;

    while((isdigit(Input[Counter]) == true)||(ispunct(Input[Counter]) == true ))//find numbers before the operator. this part isnt working as intended
    {
        NumBeforeOp = NumBeforeOp + Input[Counter];

        Counter++;
    }

    cout << "Found the number " << NumBeforeOp << " before the " << OpResult << " symbol" << endl;

    cin.get();

    Counter++; //skip the spot with the operator

    while((isdigit(Input[Counter]) == true)||(ispunct(Input[Counter]) == true ))//find numbers after the operator. this part isnt working as intended
    {
        NumAfterOp = NumAfterOp + Input[Counter];

        Counter++;
    }

    cout << "Found the number " << NumAfterOp << " after the " << OpResult << " symbol" << endl;

    cin.get();

    NumOne = atof(NumBeforeOp.c_str());//convert the first number into a double
    NumTwo = atof(NumAfterOp.c_str());//convert the second number into a double

    if(FoundAdd == true) //do the appropriate operation based on the input
    {
        Answer = NumOne + NumTwo;
    }

    if(FoundSub == true)
    {
        Answer = NumOne - NumTwo;
    }

    if(FoundMul == true)
    {
        Answer = NumOne * NumTwo;
    }

    if(FoundDiv == true)
    {
        Answer = NumOne / NumTwo;
    }

    cout << "The answer is: " << Answer << endl; //show the answer

    return 0;
}


PS - 100th post :P
Last edited on
http://www.cplusplus.com/reference/clibrary/cctype/ispunct/

"For the purpose of this function, a punctuation character is any graphic character (as in isgraph) that is not alphanumeric (as in isalnum)."... hmm, does that include whitespace also. I'll have to test it one day...

That probably includes the operators that you are trying to not get... maybe change
ispunct(Input[Counter]) == true to something like Input[Counter] == '.'


There are some issues, but the one I want to address is why didn't you make separate functions to make the flow a little easier?
#include<iostream>
#include<stack>
#include<list>
#include<queue>
#include<cstdlib>
#include<cmath>
using namespace std;

struct data
{
double x;
char ch;

data()
{
ch = ' ';
x = 1;
}
};

list<data> l;

queue<data> Q ;
queue<data> P ;
stack<char> temp;
stack<double> R;

int Priority(char ch)
{
switch(ch)
{
case '^':
return 3;
case '/':
case '*':
return 2;
case '+':
case '-':
return 1;
default:
return 0;
}
}

bool brackets(char ch)
{
switch(ch)
{
case '+':
case '-':
case '/':
case '*':
case '^':
case '(':
case ')':
return true;
default:
return false;
}
}

bool numbers(char ch)
{
if(ch == '.' || (int)ch >= 48 && (int)ch <= 57)
return true;
else
return false;
}

void Infix_To_Postfix()
{
while(P.empty() == false)
{
data ch = P.front();
P.pop();

if(ch.ch == '(')
temp.push('(');
else if(ch.ch == ')')
{
while(1)
{
char ctemp = temp.top();
temp.pop();
if(ctemp == '(' || ctemp == '\0' || temp.empty() == true)
break;
else
{
data z;
z.ch = ctemp;
Q.push(z);
}
}
}
else if(ch.ch == '+' || ch.ch == '-' || ch.ch == '/' || ch.ch == '*' || ch.ch == '^')
{
if(temp.empty() == false && Priority(temp.top()) <= Priority(ch.ch))
temp.push(ch.ch);
else
{
while(temp.empty() == false && Priority(temp.top()) > Priority(ch.ch))
{
data z;
z.ch = temp.top();
Q.push(z);
temp.pop();
}
temp.push(ch.ch);
}
}
else
Q.push(ch);
}
while(temp.empty() == false)
{
data z;
z.ch = temp.top();
Q.push(z);
temp.pop();
}
}

void solve()
{
while(Q.empty() == false)
{
data ch = Q.front();
Q.pop();


if(ch.ch == '+' || ch.ch == '*' || ch.ch == '-' || ch.ch == '/' || ch.ch == '^')
{
double op2 = R.top();
R.pop();
double op1 = R.top();
R.pop();

switch(ch.ch)
{
case '+':
op1 += op2;
break;
case '-':
op1 -= op2;
break;
case '*':
op1 *= op2;
break;
case '/':
op1 /= op2;
break;
case '^':
int x = op1;
if((int)op2 == op2)
{
for(register int i = 1 ; i < (int)op2 ; ++i)
op1 *= x;
}
else
{
op1 = pow(op1,op2);
}
break;
}
R.push(op1);
}
else if( ch.ch == ' ')
R.push(ch.x);
}
}

int main()
{
cout<<"Enter the string "<<endl;
string str;
getline(cin,str,'\n');
int i = 0 ;

while( i < str.length() )
{
if(str[i] != ' ')
{
if( brackets(str[i]) == true )
{
data temp;
temp.ch = str[i];
l.push_back(temp);
++i;
}
else if( numbers(str[i]) == true )
{
string temp = "";
while( numbers(str[i]) == true )
{
temp += str[i];
++i;
}
data temp1;
temp1.x = atof(temp.data());
l.push_back(temp1);
}
else
{
cout<<"Undefined symbol encountered : \""<<str[i]<<"\""<<endl;
return 0;
}
}
else
++i;
}
list<data>::iterator it = l.begin();
while(it != l.end())
{
P.push(*it);
++it;
}
l.clear();
Infix_To_Postfix();
solve();

cout<<"Result is \n"<<R.top()<<endl;
return 0;
}


Try to use this program instead.Actually there is an algorithm to convert our Infix notation to Postfix notation.Try to do this as Postfix(ab*) notations are easy to solve than Infix(eg:- a*b) . Also you can use any number of brackets.
Last edited on
I did this Input[Counter] == '.' and now it just adds the numbers before the decimal. I'll take a look at the above code. I probably should of used functions to clean it up
Last edited on
Here is a simpler version that uses decimals:

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
#include <iostream>
#include <string>

using namespace std;

int main()
{
    string Operator;
    double NumOne = 0;
    double NumTwo = 0;
    double Answer = 0;

    cout << "Using + for add, - for subtraction, * for multiplying, and / for divide," << endl;
    cout << "enter an arithmetic expression to calculate:" << endl;
    cin >> NumOne >> Operator >> NumTwo;

    if(Operator == "+")
    {
        Answer = NumOne + NumTwo;
    }

    else if(Operator == "-")
    {
        Answer = NumOne - NumTwo;
    }

    else if(Operator == "*")
    {
        Answer = NumOne * NumTwo;
    }

    else if(Operator == "/")
    {
        Answer = NumOne / NumTwo;
    }

    else
    {
        cout << "Operation not found. Exiting program..." << endl; //exit if theres no operator
        return 0;
    }

    cout << "The answer is: " << Answer << endl; //show the answer

    return 0;
}
Topic archived. No new replies allowed.