# Exercise 4.5 - RPN Calculator with mathematical functions¶

## Question¶

```/* Include Mathematical Functions */
- print top element of the stack,without poping
- duplicate it
- swap the top two elements
- Clear the stack  */

/* IMPORTANT: compile with -lm flag(the static math library)
For eg: gcc -lm rpn-3.c
*/

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define MAXOP 100
#define NUMBER '0'
#define NAME 'n'

int getop(char []);
void push(double);
double pop(void);
void mathfnc(char []);

/* reverse polish calculator */

int main(void)
{
int type;
double op2,op1;
char s[MAXOP];
void clearsp(void);

while((type = getop(s)) != EOF)
{
switch(type)
{
case NUMBER:
push(atof(s));
break;
case NAME:
mathfnc(s);
break;
case '+':
push(pop()+pop());
break;
case '*':
push(pop()*pop());
break;
case '-':
op2 = pop();
push(pop()-op2);
break;
case '/':
op2 = pop();
if(op2 != 0.0)
push(pop()/op2);
else
printf("error:zero divisor\n");
break;
case '%':
op2 = pop();
if(op2 != 0.0)
push(fmod(pop(),op2));
else
printf("erro:zero divisor\n");
break;
case '?':
op2=pop();
printf("\t%.8g\n",op2);
push(op2);
break;
case 'c':
clearsp();
break;
case 'd':
op2=pop();
push(op2);
push(op2);
break;
case 's':
op1=pop();
op2=pop();
push(op1);
push(op2);
break;
case '\n':
printf("\t%.8g\n",pop());
break;
default:
printf("error: unknown command %s\n",s);
break;
}
}
return 0;
}

#define MAXVAL 100

int sp = 0;
double val[MAXVAL];

void push(double f)
{
if(sp < MAXVAL)
val[sp++]=f;
else
printf("error:stack full, cant push %g\n",f);
}

double pop(void)
{
if(sp>0)
return val[--sp];
else
{
printf("error: stack empty\n");
return 0.0;
}
}

void clearsp(void)
{
sp = 0;
}

#include<ctype.h>
#include<string.h>

int getch(void);
void ungetch(int);

int getop(char s[])
{
int i,c;

while((s[0] = c = getch()) == ' ' || c =='\t')
;
s[1] = '\0';

i = 0;
if(islower(c))
{
while(islower(s[++i]=c=getch()));
;
s[i]='\0';
if(c!=EOF)
ungetch(c);
if(strlen(s)>1)
return NAME;
else
return c;
}

if(!isdigit(c) && c!='.' && c!='-')
return c;

if(c=='-')
if(isdigit(c=getch()) || c == '.')
s[++i]=c;
else
{
if(c!=EOF)
ungetch(c);
return '-';
}

if(isdigit(c))
while(isdigit(s[++i] =c =getch()))
;

if(c=='.')
while(isdigit(s[++i] = c=getch()))
;

s[i] = '\0';
if(c!=EOF)
ungetch(c);
return NUMBER;
}

#define BUFSIZE 100

char buf[BUFSIZE];
int bufp = 0;

int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}

/* mathfnc: check the string s for supported math function */

void mathfnc(char s[])
{
double op2;

if(strcmp(s,"sin")==0)
push(sin(pop()));
else if(strcmp(s,"cos")==0)
push(cos(pop()));
else if(strcmp(s,"exp")==0)
push(exp(pop()));
else if(strcmp(s,"pow")==0)
{
op2 = pop();
push(pow(pop(),op2));
}
else
printf("error: %s is not supported\n",s);
}
```

## Explanation¶

The RPN calculator has addition features like doing mathematical functions. In the input, if a string is given then the calculator identifies it as a NAME and goes to the mathfun.

In the mathfun, the string input is compared with “sin” and if it is a sin, the mathematical function sin is called on the popped value. If the intput is cos, the cosine function is called and if the input is “pow”, then first value is popped and stored in op2 and second value is raised to the power of op2.

The curx of program is in this function.

```void mathfnc(char s[])
{
double op2;

if(strcmp(s,"sin")==0)
push(sin(pop()));
else if(strcmp(s,"cos")==0)
push(cos(pop()));
else if(strcmp(s,"exp")==0)
push(exp(pop()));
else if(strcmp(s,"pow")==0)
{
op2 = pop();
push(pow(pop(),op2));
}
else
printf("error: %s is not supported\n",s);
}
```