We first need to find a way to create commands for the various
functions. We could use a single character like before, but it would be
more convenient for the user to type in the word itself like
sin or pow. To do this, we first create a new
function called lookfor
, which takes in a string and
returns 1
if it is found on the input stream. We can look
for the string by using a loop that continues to read in the next
character until the input no longer matches the string or if the string
is found. If the string was not found, the function will execute
ungetch
for any characters it had read in, and return
0
.
...
/* lookfor: return 1 if specified string is found */
int lookfor(char s[])
{
int i, j;
char temp[MAXOP];
for (i = 0; s[i] != '\0' && (temp[i] = getch()) == s[i]; ++i)
;
if (s[i] == '\0') /* string was found */
return 1;
else { /* unget read characters and return 0 */
for (j = 0; j <= i; ++j)
ungetch(temp[j]);
return 0;
}
}
Now inside getop
, when the character we come across is not
the start of a number, instead of directly returning it, we enter a
switch
, where we see if a function name is found. For
example, one of the cases inside the switch
is
's'
; when it occurs, we call lookfor("in")
(altogether, we would be looking for sin.) If the string is
found, we return a SIN
token; otherwise, we simply return
's'
.
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#include <ctype.h>
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
#define SIN 'S' /* signal that a sin function was found */
#define EXP 'E' /* signal that a exp function was found */
#define POW 'P' /* signal that a pow function was found */
#define MAXVAL 100 /* maximum depth of val stack */
#define BUFSIZE 100
...
/* getop: get next operator or numeric operand */
int getop(char s[])
{
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.' && c != '+' && c != '-') {
switch (tolower(c)) {
case 's':
return (lookfor("in")) ? SIN : c;
case 'e':
return (lookfor("xp")) ? EXP : c;
case 'p':
return (lookfor("ow")) ? POW : c;
default:
return c; /* not a number */
}
}
Finally, we need to add the cases for each of our tokens inside of
main
. The functions themselves come from
<math.h>
. sin
and exp
need
one input, and pow
requires two.
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#include <ctype.h>
#include <math.h>
...
/* reverse Polish calculator */
main()
{
int type;
double op1, op2;
char s[MAXOP];
while ((type = getop(s)) != EOF) {
switch (type) {
...
case SIN:
push(sin(pop()));
break;
case EXP:
push(exp(pop()));
break;
case POW:
op2 = pop();
push(pow(pop(), op2));
break;
case 'p':
print_val();
break;
case 'd':
duplicate();
break;
case 's':
swap();
break;
case 'c':
clear();
break;
case '\n':
if (sp == 1)
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}
return 0;
}
...
Note: if you are using gcc
, in order to compile
code that uses the math header, you will need to use gcc
's
-lm
option (e.g. gcc -lm /path/to/file.c.)