lolamontes69

K+R Exercise4_7

Sep 7th, 2014
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.52 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>    /*for atof() */
  3. #include <ctype.h>
  4. #include <math.h>
  5. #include <string.h>
  6.  
  7. #define MAXOP   100    /* max size of operand or operator */
  8. #define MAXVAL  100    /* maximum depth of val stack      */
  9. #define NUMBER  '0'    /* signal that a number was found  */
  10. #define BUFSIZE 100    /* buffer for ungetch              */
  11. #define VARIABLE '1'   /* signal that a variable value was added to stack  */
  12.  
  13.  
  14.  
  15. /* Main functions */
  16. int    getop(char s[]);
  17. void   push(double f);
  18. double pop(void);
  19. int    getch(void);
  20. void   ungetch(int);
  21.  
  22. /* Command functions */
  23. void clearstack(void);     /* Command 'cs' Clear current stack   */
  24. void cleardupl(void);      /* Command 'cd' Clear duplicate stack */
  25. void stackprint(void);     /* Command 'ps' Print current stack   */
  26. void dsprint(void);        /* Command 'pd' Print duplicate stack*/
  27. void duplstack(void);      /* Command 'du' Duplicate stack print */
  28. void swaptop(void);        /* Command 'sw' Swap top two elements of stack */
  29. void help(void);           /* Command 'help' Print 'help screen' */
  30. void errorMSG(void);       /* Simple error message */
  31. void ungets(char s[]);     /* Put whole string onto input */
  32.  
  33. /* External variables */
  34. int sp = 0;                /* Next free stack position        */
  35. double val[MAXVAL];        /* value stack                     */
  36. char buf[BUFSIZE];
  37. int bufp = 0;              /* next free position in buffer    */
  38.  
  39. double dupval[MAXVAL];     /* saved stack duplicate        */
  40. int dss = 0;               /* duplicate stack size for printing out dupval */
  41.  
  42. int NOPOP = 0;             /* try not to pop stack after typing in help */
  43.  
  44. double VARS[26];           /* an array to store the variables in, initialize
  45.                               in main, double so its compatible */
  46.  
  47. char PI[] = "3.1415926535897931";
  48.  
  49. /* main program:  A Reverse Polish calculator. */
  50. main()
  51. {
  52.     int i, type;
  53.     double op2;
  54.     double mod;
  55.     char s[MAXOP];
  56.  
  57.     /* Initialize variable array */
  58.     for(i=0; i<=25; ++i)
  59.         VARS[i]=0;
  60.  
  61.     while((type = getop(s)) != EOF) {
  62.         switch(type) {
  63.         case VARIABLE:
  64.             break;                 /* Variable already added to stack in getop() */
  65.         case NUMBER:
  66.             NOPOP=0;
  67.             push(atof(s));         /* Add number to stack   */
  68.             break;
  69.         case '+':
  70.             NOPOP=0;
  71.             push(pop() + pop());   // pop last number from stack and add to previous
  72.             break;                 // number from stack then add to stack as last item
  73.         case '*':
  74.             NOPOP=0;
  75.             push(pop() * pop());   // as above with *
  76.             break;
  77.         case '-':                  // pop last number from stack save as op2
  78.             NOPOP=0;
  79.             op2 = pop();           // pop previous number from stack
  80.             push(pop() - op2);     // otherwise would produce op2 - pop()
  81.             break;                 // and push to stack replacing them
  82.         case '/':
  83.             NOPOP=0;
  84.             op2 = pop();           // as for '-' but with an errorcheck for
  85.             if(op2!=0.0)           // division by zero
  86.                 push(pop()/op2);
  87.             else
  88.                 printf("error: zero divisor\n");
  89.             break;
  90.         case '\%':
  91.             NOPOP=0;
  92.             op2 = pop();            // as for '-' but with an errorcheck for
  93.             mod = pop();            // % cannot be applied to float or double
  94.             if(op2!=0.0) {          // so do the math here instead.
  95.                 if(mod>0 && op2>0) {
  96.                     while(mod-op2>=0)
  97.                         mod = mod - op2;
  98.                 }
  99.                 else if(mod<0 && op2>0) {
  100.                     mod = mod-mod-mod;
  101.                     while(mod-op2>=0)
  102.                         mod = mod - op2;
  103.                 }
  104.                 else if(mod<0 && op2<0) {
  105.                     mod = mod-mod-mod;
  106.                     op2 = op2-op2-op2;
  107.                     while(mod-op2>=0)
  108.                         mod = mod - op2;
  109.                     mod = mod-mod-mod;
  110.                 }
  111.                 else if(mod>0 && op2<0) {
  112.                     op2 = op2-op2-op2;
  113.                     while(mod-op2>=0)
  114.                         mod = mod - op2;  
  115.                     mod = mod-mod-mod;
  116.                 }
  117.                 push(mod);
  118.             }
  119.             else
  120.                 printf("error: zero divisor\n");
  121.             break;
  122.         case '\n':                      // if end of equation pop last item from stack
  123.             if(NOPOP==0) printf("\t%.8g\n", pop());  // aka the answer
  124.             NOPOP=0;
  125.             break;
  126.         default:
  127.             NOPOP=0;
  128.             printf("error: unknown command %s\n", s);  // None of the above
  129.             break;                                     // You dun goofed
  130.         }
  131.     }
  132.     return 0;
  133. }
  134.  
  135. /* ////////////// MAIN FUNCTIONS ////////////// */
  136.  
  137. /* errorMSG: a simple error message */
  138. void errorMSG(void)
  139. {
  140.     NOPOP=1;
  141.     puts("<<<Invalid Command>>>");
  142. }
  143.  
  144. /* getop: get next character or numeric operand */
  145. int getop(char s[])
  146. {
  147.     int i, c, asc, asc1, index, index1;
  148.     double l, op2;  /* Used to keep answer passed to push() compatible */
  149.  
  150.     do {
  151.     while((s[0] = c = getch()) == ' ' || c == '\t')
  152.         ;
  153.     i = 0;
  154.     if(isupper(c)) {
  155.         asc = c;
  156.         index = asc-65;
  157.         while((s[0] = c = getch()) == ' ' || c == '\t')
  158.             ;
  159.         if(c=='=') {
  160.             while((s[0] = c = getch()) == ' ' || c == '\t')
  161.                 ;
  162.             if(isdigit(c)) {
  163.                 while(isdigit(s[++i] = c = getch()))
  164.                     ;
  165.                 if(c == '.')    
  166.                     while(isdigit(s[++i] = c = getch()))
  167.                         ;
  168.                 s[i] = '\0';
  169.                 if(c != EOF)
  170.                     ungetch(c);
  171.                 VARS[index] = atof(s);
  172.                 NOPOP=1;
  173.             }
  174.             else if(isupper(c)) {
  175.                 asc1 = c;
  176.                 index1 = asc1-65;
  177.                 VARS[index]=VARS[index1];
  178.             }
  179.             else return(c);
  180.         }
  181.         else {
  182.             l = VARS[index];   // Get the value of the variable and
  183.             NOPOP=0;           // and push it to the stack.
  184.             if(c != EOF)
  185.                 ungetch(c);
  186.             push(l);
  187.             return VARIABLE;
  188.         }
  189.         // if not an assignment get value here and deal with errors
  190.         while((s[0] = c = getch()) == ' ' || c == '\t')
  191.             ;
  192.     }
  193.     i=0;
  194.     if(c=='c') {
  195.         s[0] = c = getch();
  196.         if(c =='s') clearstack();       /* cs - Clear current stack    */
  197.         else if(c=='d') cleardupl();    /* cd - Clear duplicate stack   */
  198.         else if(c=='o') {
  199.             s[0] = c = getch();
  200.             if(c=='s') {                /* cos - cos(x) function */
  201.                 l = cos(pop());
  202.                 NOPOP=0;
  203.                 push(l);                /* push to stack here */
  204.             }
  205.             else errorMSG();
  206.         }
  207.         else errorMSG();
  208.         while((s[0] = c = getch()) == ' ' || c == '\t')
  209.             ;
  210.     }
  211.     else if(c=='d') {
  212.         s[0] = c = getch();
  213.         if(c =='u') duplstack();        /* du - Make duplicate of current stack */
  214.         else errorMSG();
  215.         while((s[0] = c = getch()) == ' ' || c == '\t')
  216.             ;
  217.     }
  218.     else if(c=='e') {
  219.         s[0] = c = getch();
  220.         if(c=='x') {
  221.             s[0] = c = getch();
  222.             if(c=='p') {                /* exp - exp(x) function */
  223.                 l = exp(pop());
  224.                 NOPOP=0;
  225.                 push(l);                /* push to stack here */
  226.             }
  227.             else errorMSG();
  228.         }
  229.         else errorMSG();
  230.         while((s[0] = c = getch()) == ' ' || c == '\t')
  231.             ;
  232.     }
  233.  
  234.     else if(c=='h') {
  235.         s[0] = c = getch();
  236.         if(c =='e') {          /* help - Print 'Help screen' */
  237.             s[0] = c = getch();
  238.             if(c =='l') {
  239.                 s[0] = c = getch();
  240.                 if(c =='p') {
  241.                     help();
  242.                 }
  243.                 else errorMSG();
  244.             }
  245.             else errorMSG();
  246.         }
  247.         else errorMSG();
  248.         while((s[0] = c = getch()) == ' ' || c == '\t')
  249.             ;
  250.     }
  251.     else if(c=='p') {
  252.         s[0] = c = getch();
  253.         if(c =='s') stackprint();       /* ps - Print current stack   */
  254.         else if(c=='d') dsprint();      /* pd - Print duplicate stack   */
  255.         else if(c=='o') {
  256.             s[0] = c = getch();
  257.             if(c=='w') {                /* pow - pow(x,y) function */
  258.                 op2 = pop();
  259.                 l = pow(pop(),op2);           //    pow(x,y)   x**y
  260.                 NOPOP=0;
  261.                 push(l);                /* push to stack here */
  262.             }
  263.             else errorMSG();
  264.         }
  265.         else if(c=='i') ungets(PI);      /* pi: put value of pi onto input */
  266.         else errorMSG();
  267.         while((s[0] = c = getch()) == ' ' || c == '\t') // Skip spaces and tabs
  268.             ;
  269.     }
  270.     else if(c=='s') {
  271.         s[0] = c = getch();
  272.         if(c =='w') swaptop();          /* sw - Swap top two elements in current stack */
  273.         else if(c=='i') {
  274.             s[0] = c = getch();
  275.             if(c=='n') {                /* sin - sin(x) function */
  276.                 l = sin(pop());
  277.                 NOPOP=0;
  278.                 push(l);                /* push to stack here */
  279.             }
  280.             else errorMSG();
  281.         }
  282.         else if(c=='q') {
  283.             s[0] = c = getch();
  284.             if(c=='r') {                /* sqrt - sqrt(x) function */
  285.                 s[0] = c = getch();
  286.                 if(c=='t') {
  287.                     l = sqrt(pop());
  288.                     NOPOP=0;
  289.                     push(l);                /* push to stack here */
  290.                 }
  291.                 else errorMSG();
  292.             }
  293.             else errorMSG();
  294.         }
  295.         else errorMSG();
  296.         while((s[0] = c = getch()) == ' ' || c == '\t')
  297.             ;
  298.     }
  299.     else if(isalpha(c) && islower(c)) errorMSG();
  300.     }  /* End of do while*/
  301.     while(isalpha(c) && islower(c));
  302.     s[0] = c;
  303.     s[1] = '\0';
  304.     if(!isdigit(c) && c != '.' && c != '-')
  305.         return c;      /* Not a number          */
  306.     i = 0;
  307.     if(c == '-'){      /* collect fraction part */
  308.         NOPOP=0;
  309.         if(!isdigit(s[++i] = c = getch())) {
  310.            
  311.             if(c != EOF)     // if an extra char and not a digit
  312.                 ungetch(c);  // put into buffer (eg 4 4 * help
  313.             return '-';
  314.         }
  315.     }
  316.  
  317.     if(isdigit(c))    /* collect integer part  */
  318.         while(isdigit(s[++i] = c = getch()))
  319.             ;
  320.     if(c == '.')      /* collect fraction part */
  321.         while(isdigit(s[++i] = c = getch()))
  322.             ;
  323.     s[i] = '\0';
  324.     if(c != EOF)
  325.         ungetch(c);
  326.     return NUMBER;
  327. }
  328.  
  329. /* push: push f onto value stack    */
  330. void push(double f)
  331. {
  332.  
  333.     if(sp < MAXVAL) {
  334.         val[sp++] = f;     // Add item as stack[sp] then increment sp
  335.     }
  336.     else
  337.         printf("error: stack full, cant push %g\n", f);
  338. }
  339.  
  340. /* pop: pop and return top value from stack */
  341. double pop(void)
  342. {
  343.     if(sp > 0) {
  344.         if(NOPOP==0) return val[--sp];   // return last item in stack first decrementing sp
  345.         else NOPOP=0;
  346.     }
  347.     else {
  348.         if(NOPOP==0) {
  349.             printf("error: stack empty\n");
  350.             return 0.0;
  351.         }
  352.         else NOPOP=0;
  353.     }
  354. }
  355.  
  356. /* get a (possibly pushed-back) character */
  357. int getch(void)
  358. {
  359.     return (bufp > 0) ? buf[--bufp] : getchar();  
  360. }
  361.  
  362. /* push character back on input */
  363. void ungetch(int c)
  364. {
  365.     if(bufp >= BUFSIZE)
  366.         printf("ungetch: too many characters\n");
  367.     else
  368.         buf[bufp++] = c;  // Add character to buffer and increment bufp
  369. }
  370.  
  371. /* ////////////// COMMAND FUNCTIONS ////////////// */
  372.  
  373. /* ungets: push a whole string onto input */
  374. void ungets(char s[])
  375. {
  376.     int len = strlen(s);
  377.  
  378.     while(len>0)
  379.         ungetch(s[--len]);
  380. }
  381.  
  382.  
  383. /* clearstack: Clear current stack  */
  384. void clearstack(void)
  385. {
  386.     sp=0;
  387.     puts("Stack cleared");
  388.     NOPOP=1;
  389. }
  390.  
  391. /* cleardupl: Clear duplicate stack */
  392. void cleardupl(void)
  393. {
  394.     dss=0;
  395.     puts("Duplicate stack cleared");
  396.     NOPOP=1;
  397. }
  398.  
  399. /* stackprint: print out current stack */
  400. void stackprint(void)
  401. {
  402.     int spp = sp;
  403.  
  404.     if(spp<=0) printf("error: stack empty\n");
  405.     else {
  406.         printf("--Top of current stack--\n");
  407.         while(spp>sp-2)                    // Note > 0 to print full stack
  408.             printf("%9g\n", val[--spp]);   // print last item in stack
  409.         printf("-------------\n");
  410.     }
  411.     NOPOP=1;
  412. }
  413.  
  414. /* dsprint: print out the duplicate stack top down */
  415. void dsprint(void)
  416. {
  417.     int spp = dss;
  418.  
  419.     if(spp<=0) printf("error: duplicate stack empty\n");
  420.     else {
  421.         printf("--duplicate stack--\n");
  422.         while(spp>0)                    // Note > 0 to print full stack
  423.             printf("%9g\n", val[--spp]);   // print last item in stack
  424.         printf("--end of duplicate stack --\n");
  425.     }
  426.     NOPOP=1;
  427. }
  428.  
  429. /* duplstack: make duplicate of the current stack */
  430. void duplstack(void)
  431. {
  432.     dss=0;
  433.  
  434.     if(sp<=0) printf("error: can't duplicate, stack is empty\n");
  435.     else {
  436.         while(dss<sp) {
  437.             dupval[dss] = val[dss];  
  438.             dss++;
  439.         }
  440.     puts("Duplicate stack created");
  441.     }
  442.     NOPOP=1;
  443. }
  444.  
  445. /* swaptop: Swap top two elements of stack */
  446. void swaptop(void)
  447. {
  448.     double temp;
  449.  
  450.     if(sp<=0) printf("error: stack empty\n");
  451.     else if(sp==1) printf("error: \n");
  452.     else {
  453.         temp = val[sp-1];
  454.         val[sp-1]=val[sp-2];
  455.         val[sp-2]=temp;
  456.         puts("Top two elements of stack swapped");
  457.     }
  458.     NOPOP=1;
  459. }
  460.  
  461. /* help: Print out help on available commands */
  462. void help(void)
  463. {
  464.     puts("------------------------------");
  465.     puts("Help: Commands");
  466.     puts("cs   - Clear current stack");
  467.     puts("cd   - Clear duplicate stack");
  468.     puts("ps   - Print current stack");
  469.     puts("pd   - Print duplicate stack");
  470.     puts("sw   - Swap top two elements in current stack");
  471.     puts("du   - Make duplicate of current stack");
  472.     puts("help - Print this 'Help screen'");
  473.     puts("------------------------------");
  474.     puts("Help: Functions");
  475.     puts("pi - add the value of pi to the input line");
  476.     puts("x cos");
  477.     puts("x exp");
  478.     puts("x y pow");
  479.     puts("x sin");
  480.     puts("x sqrt");
  481.     puts("------------------------------");
  482.     NOPOP=1;
  483. }
Advertisement
Add Comment
Please, Sign In to add comment