Modify getop so that it doesn’t need to use ungetch. Hint: use an internal static variable.

#include <stdio.h>
#include <ctype.h>

#define   NUMBER  '0'   /*signal that a number was found */

int getch(void);

/*getop: get next operator or numeric operand  */
int getop(char s[]){
    int c, i;
    static int lastc = 0;

    if(lastc == 0)
      c =getch();
    else{
      c =lastc;
      lastc = 0;
    }
    while((s[0] = c) == ' ' || c == '\t')
           c =getch();
    s[i] = '\0';
   if (!isdigit(c) && c != '.')
         return c;
   i = 0;
   if (isdigit(c))          /* collect integer part */
      while(isdigit(s[++i] = c =getch())
           ;
   s[i] = '\0';
   if (c != EOF)
       lastc =c ;
   return NUMBER;
}

Write an alternate getline to read an entire input line:this makes getch and ungetch unnecessary.Revise the calculator to use this approach.

#include <stdio.h>
#include <ctype.h>

#define   MAXLINE   100
#define   NUMBER   '0'  /* signal that a number was found */

int getline(char line[], int limit);

int li = 0;   /*input line index */
char line[MAXLINE];    /* one input line */

/* getop: get next operator or numeric operand    */
int getop(char s[]){
    int c, i;

    if(line[li] =='\0')
        if(getline(line, MAXLINE) == 0)
             return EOF;
        else
            li = 0;
    while ((s[0] = c = line[li++]) == ' ' || c == '\t')
              ;
    s[i] = '\0';
    if (!isdigit(c) && c != '.')
         return c;     /* not a number */
    i = 0;
   if (isdigit(c))     /* collect  integer part */
       while(isdigit(s[++i] = c =line[li++]))
          ;
   if(c == '.')   /* collect fraction part */
       while(isdigit(s[++i) =c =line[i++]))
           ;
   s[i] = '\0';
   li--;
   return NUMBER;
}

implement getch and ungetch to handle pushed-back EOF correctly.

#include <stdio.h>

#define BUFSIZE  100

int buf[BUFSIZE];     /*buffer for ungetch       */
int bufp = 0;    /*next free position in buf */

/*getch: get a (possibly pushed back) character    */
int getch(void){
    return (bufp > 0) ? buf[--bufp): getchar();
}
/*ungetch: push character back onto the input */
void ungetch(int c){
     if (bufp >= BUFSIZE)
          printf("ungetch: too many characters\n");
     else
          buf[bufp++] = c;
}

Extend the reverse polish calculator.

#include<stdio.h>
#include<math.h>    /* for atof() */

#define   MAXOP      100   /* max size of operand or operator */
#define   NUMBER     '0'  /* signal that a number was found */

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

/* reverse polish calculator */
int main(){
    int i, type, var =0;

    double   op2, v;
    char     s[MAXOP];
    double   variable[26];

   for(i =0; i < 26;i++)
       variable[i] = 0.0;
   while((type =getop(s)) != EOF){
       switch(type){
           case NUMBER:
                push(atof(s));
                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 '=':
                  pop();
                  if (var >= 'A' && var <= 'Z')
                       variable[var -'A'] = pop();
                  else
                      printf("error: no variable name\n");
                  break;
         case '\n':
              v = pop();
              printf("\t %.8g\n", v);
              break;
         default:
             if (type >='A'  && type <= 'Z')
                  push(variable[type - 'A']);
              else if (type == 'v')
                  push(v);
             else
                 printf("error: unknown command %s\n", s);
             break;
       }
        var = type;
   }
    return 0;
}

Extend atof to handle scientific notation of the form 123.45e-6

#include <ctype.h>

/*atof: convert string s to double */
double atof(char s[]){
     double val, power;
     int exp, i, sign;

     for(i =0; isspace(s[i]); i++)  /* skip white space */
           ;
     sign = (s[i] == '-') ? -1: 1;
     if(s[i] == '+' || s[i] == '-')
           i++;
     for(val =0.0; isdigit(s[i]); i++)
         val = 10.0 * val + (s[i] - '0');
     if (s[i] == '.')
         i++;
     for (power = 1.0; isdigit(s[i]); i++){
          val = 10.0 * val + (s[i] - '0');
          power *= 10.0;
     }
      val = sign * val / power;
    if (s[i] == 'e' || s[i] == 'E'){
        sign = (s[++i] == '-') ? -1 : 1;
        if (s[i] =='+' || s[i] == '-')
             i++;
        for(exp = 0; isdigit(s[i]); i++)
            exp = 10 * exp + (s[i] - '0');
        if (sign == 1)
            while (exp-- > 0)   /* positive exponent */
                  val *= 10;
       else
           while (exp-- > 0)  /* negative exponent   */
                val /= 10;
    }
     return val;
}

Write the function strrindex(s, t) , which returns the position of the rightmost occurrence of t in s, or -1 if there is none.

/*strrindex:returns rightmost index of t in s, -1 if none */
int strrindex(char s[], char t[]){
    int i, j, k, pos;
  
    pos = -1;
    for(i = 0; s[i] != '\0'; i++){
       for(j = i, k =0; t[k] != '\0' && s[j] == t[k]; j++, k++)
              ;
       if( k > 0 && t[k] == '\0')
           pos = i;
    }
    return pos;
}


/*A more efficient solution to the same problem */
#include <string.h>
/*strrindex :returns rightmost index of t in s , -1 if none */
int strrindex(char s[], char t[]){
    int i, j, k;

    for (i = strlen(s) - strlen(t); i >= 0; i--){
       for (j =1, k=0; t[k] != '\0' && s[j] == t[k];j++, k++)
                  ;
       if (k > 0 && t[k] == '\0')
            return i;
    }
    return -1;
}

Write a version of itoa that accepts three arguments instead of two.The third argument is a minimum field width; the converted number must be padded with blanks to make it wide enough.

#define   abs(x)    ((x)  < 0 ? -(x) : (x))

/* itoa: convert n to characters in s, w characters wide */
void itoa(int n, char s[], int w){
     int i, sign;
     void reverse(char s[]);

    sign = n;  /*record sign */
    i = 0;
    do{
      s[i++] = abs(n % 10) + '0'; /* get next digit */
    }while((n /= 10) != 10);  /*delete it */
    if (sign < 0)
        s[i++] = '-';
    while(i < w)
       s[i++] = ' ';      /* pad with blanks */
    s[i] = '\0';
    reverse(s);
}

Write the function itob(n ,s , b) that converts the integer n into a base b character representation in the string s.In particular, itob(n, s, 16) formats n as a hexadecimal integer in s.

/*itob: convert n to characters in s - base b    */
void itob(int n, char s[], int b){
     int i, j, sign;
     void reverse(char s[]);
     
     if ((sign = n) < 0)
         n = -n ;     /* record sign  */
     i = 0;
     do{
              /* generate digits in reverse order */
          j = n % b;         /* get next digit */
          s[i++] = ( j <= 9) ? j + '0' : j + 'a' - 10;
     } while (( n /= b) > 0);  /* delete it */
    if (sign < 0)
         s[i++] = '-';
    s[i] = '\0';
    reverse(s);
}