C++ Programming Exercise:

Implement a command-line calculator that allows the user to enter an expression containing numbers, variables, brackets, and operators. The calculator will also allow assignments to a variable. After the user enters the expression the program will evaluate it and display the value. If the expression is part of an assignment its value will be also be stored in the variable. The operators are +, -, *, /, % and ^ (exponentiation). (These are all binary operators.) % should be applicable to floating point numbers and work like it does in Java. There are three types of bracket: parentheses ( ( ) ) , square brackets ( [ ] ) and braces ( {} ). A variable may be any single lowercase letter. (Uninitialized variables can have any value.) The calculator will loop until the user enters a blank line. Here is a sample run below:

``````> 3 + 4.5

7.5

> a = 6*2/5

2.4

> b = a+1

3.4

> b

3.4

> c = b^2

11.56

> a * {b – (c + 0.84)}

-21.6

> 7.5 % 3

1.5

> 5 % -2

1

> -5 % 2

-1

> a = 1 / 0

infinity

> 1 / a

0

> a / a

NaN

> d = (-1)^0.5

NaN

> d / d

NaN

> + 4 5

illegal expression

> 4 + -c

illegal expression

>

Bye!
``````

Use a two step process (infix -> postfix -> value). Provide a debugging mode where you also output the equivalent postfix expression:

``````> 5 + 4 * 2

5 4 2 * +

13

>
``````

Convert all input to type double and display results with reasonable precision. The default precision is probably OK (e.g. 0.333333 for 1/3.0). Don’t add “bells and whistles” or make those things part of a mode that can be turned on or off. Input should be accepted with or without spaces. For example 2+2, 2 +2 and 2 + 2 should all work. A minus sign can be part of a number (e.g. 4+-6) or a binary operator (e.g. 4–a). A minus is never a unary operator (so 4+-a would be illegal).

Here is my solution for this code:

``````#include <iostream>
#include <cmath>
#include <stack>

using namespace std;

stack <char> st;
stack <double> sti;

char var[20];
double data[20];
int no_of_var=0;

struct exp
{
char type;
double val;
}e[100];

int i=0;

int priority ( char c )
{
if ( c == '^' )
return 3 ;
if ( c == '*' || c == '/' || c == '%' )
return 2 ;
else
{
if ( c == '+' || c == '-' )
return 1 ;
else
return 0 ;
}
}

double search(char c,int *fl)
{
int j=0;

for(j=0;j<no_of_var;j++)
if(var[j]==c)
{
*fl=j;
return data[j];
}

*fl=-1;
return -1;
}

void create(char *s, double v)
{
double n;
int fl;

n = search(*s,&fl);

if(fl>=0)
{
var[fl] = *s;
data[fl] = v;
}
else
{
var[no_of_var] = *s;
data[no_of_var++] = v;
}
}

void convert(char *s )
{
char temp[100];
char *t = temp;
double n,d;
int fl;
i=0;

while ( *s )
{
if ( isdigit ( *s ) || *s=='.')
{
n=0;d=1;
while ( isdigit ( *s ) )
{
n = n*10+ (*s-'0') ;
s++ ;
}

if(*s=='.')
{
s++;
while(isdigit ( *s ))
{
n = n + (*s-'0')/pow(10,d++);
s++;
}
}
e[i].type='n';
e[i++].val=n;
}
if(isalpha(*s))
{
n = search(*s++,&fl);
if(fl==-1)
{
return;
}
e[i].type='n';
e[i++].val=n;
}
if ( *s == '(' || *s == '[' || *s == '{')
{
st.push ( *s ) ;
s++ ;
}
char opr ;
if ( *s == '*' || *s == '+' || *s == '/' || *s == '%' || *s == '-' || *s == '^' )
{
if ( !st.empty() )
{
opr = st.top() ;
st.pop();
while ( priority ( opr ) >= priority ( *s ) && !st.empty() )
{
e[i].type='o';
e[i++].val=opr;

opr = st.top() ;
st.pop();
}
st.push ( opr ) ;
st.push ( *s ) ;
}
else
st.push ( *s ) ;
s++ ;
}
if ( *s == ')' )
{
opr = st.top( ) ;
st.pop();
while ( ( opr ) != '(' )
{
e[i].val = opr ;
e[i++].type='o';

opr = st.top( ) ;
st.pop();
}
s++ ;
}
if ( *s == ']' )
{
opr = st.top( ) ;

st.pop();
while ( ( opr ) != '[' )
{
e[i].val = opr ;
e[i++].type='o';
opr = st.top( ) ;
st.pop();
}
s++ ;
}
if ( *s == '}' )
{
opr = st.top( );
st.pop();
while ( ( opr ) != '{' )
{
e[i].val = opr ;
e[i++].type='o';
opr = st.top( ) ;
st.pop();
}
s++ ;
}
}
while ( !st.empty() )
{
char opr = st.top( ) ;
st.pop();
e[i].val = opr ;
e[i++].type='o';
}

}

void clear()
{
while(!st.empty())
st.pop();

while(!sti.empty())
sti.pop();

}

double calculate()
{
clear();

int j=0;
double n1, n2, n3,nn ;
while ( j<i )
{
if ( e[j].type=='n' )
{
sti.push ( e[j].val ) ;
}
else
{
n1 = sti.top( ) ;
sti.pop();
n2 = sti.top( ) ;
sti.pop();

switch ( char(e[j].val) )
{
case '+' :
n3 = n2 + n1 ;
break ;
case '-' :
n3 = n2 - n1 ;
break ;
case '/' :
n3 = n2 / n1 ;
break ;
case '*' :
n3 = n2 * n1 ;
break ;
case '%' :
n3 = int(n2) % int(n1) ;
break ;
case '^' :
n3 = pow ( n2 , n1 ) ;
break ;
default :
cout << "Unknown operator" ;
exit ( 1 ) ;
}

sti.push ( n3 ) ;
}
j++ ;
}

return sti.top();
}

int chk(char *s)
{
int v;
char *t;

t = s;

while(*s)
{
if(*s=='-' && ( *(s+1) >= 'a' && *(s+1) <= 'z' ))
{
cout<<"\n - as unary operator not allowed !!";
return -1;
}
s++;
}

s = t;
while(*s)
{
if(*s++ == '=')
{
if(*t >='a' && *t <= 'z')
{
convert(s);
v = calculate();

create(t,v);
return 1;
}
else
{
cout<<"\n Only lower case letters allowed !";
return -1;
}

}
}

return 0;
}

int main( )
{
char expr[100] ;
int r;

while(1)
{
cout<<"\n>";
cin.getline ( expr, 100 ) ;

if(strlen(expr)==0)
break;

r = chk(expr);

if(r==0)
convert(expr);
else if(r==1)
cout<<endl<<calculate();

}

}
``````

My problem is when I tested the program, I am not getting any output for the postfix expression or the result of the calculation or a blank line. When I input an expression, it keeps going to the next input instead of producing the output for the previous input. Also, for variable assignments, I keep getting this message "Unknown operator." Can someone help me fix this problem?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.