Exercise 4-5

Add access to library functions like sin, exp, and pow. See <math.h> in Appendix B, Section 4.

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.)