lolamontes69

K+R Exercise4_9

Sep 7th, 2014
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.42 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. int 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.     printf("\nTop of the stack\t%.8g\n", pop());
  133.     return 0;
  134. }
  135.  
  136. /* ////////////// MAIN FUNCTIONS ////////////// */
  137.  
  138. /* errorMSG: a simple error message */
  139. void errorMSG(void)
  140. {
  141.     NOPOP=1;
  142.     puts("<<<Invalid Command>>>");
  143. }
  144.  
  145. /* getop: get next character or numeric operand */
  146. int getop(char s[])
  147. {
  148.     int i, c, asc, asc1, index, index1;
  149.     double l, op2;  /* Used to keep answer passed to push() compatible */
  150.  
  151.     do {
  152.     while((s[0] = c = getch()) == ' ' || c == '\t')
  153.         ;
  154.     i = 0;
  155.     if(isupper(c)) {
  156.         asc = c;
  157.         index = asc-65;
  158.         while((s[0] = c = getch()) == ' ' || c == '\t')
  159.             ;
  160.         if(c=='=') {
  161.             while((s[0] = c = getch()) == ' ' || c == '\t')
  162.                 ;
  163.             if(isdigit(c)) {
  164.                 while(isdigit(s[++i] = c = getch()))
  165.                     ;
  166.                 if(c == '.')    
  167.                     while(isdigit(s[++i] = c = getch()))
  168.                         ;
  169.                 s[i] = '\0';
  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.             ungetch(c);
  185.             push(l);
  186.             return VARIABLE;
  187.         }
  188.         // if not an assignment get value here and deal with errors
  189.         while((s[0] = c = getch()) == ' ' || c == '\t')
  190.             ;
  191.     }
  192.     i=0;
  193.     if(c=='c') {
  194.         s[0] = c = getch();
  195.         if(c =='s') clearstack();       /* cs - Clear current stack    */
  196.         else if(c=='d') cleardupl();    /* cd - Clear duplicate stack   */
  197.         else if(c=='o') {
  198.             s[0] = c = getch();
  199.             if(c=='s') {                /* cos - cos(x) function */
  200.                 l = cos(pop());
  201.                 NOPOP=0;
  202.                 push(l);                /* push to stack here */
  203.             }
  204.             else errorMSG();
  205.         }
  206.         else errorMSG();
  207.         while((s[0] = c = getch()) == ' ' || c == '\t')
  208.             ;
  209.     }
  210.     else if(c=='d') {
  211.         s[0] = c = getch();
  212.         if(c =='u') duplstack();        /* du - Make duplicate of current stack */
  213.         else errorMSG();
  214.         while((s[0] = c = getch()) == ' ' || c == '\t')
  215.             ;
  216.     }
  217.     else if(c=='e') {
  218.         s[0] = c = getch();
  219.         if(c=='x') {
  220.             s[0] = c = getch();
  221.             if(c=='p') {                /* exp - exp(x) function */
  222.                 l = exp(pop());
  223.                 NOPOP=0;
  224.                 push(l);                /* push to stack here */
  225.             }
  226.             else errorMSG();
  227.         }
  228.         else errorMSG();
  229.         while((s[0] = c = getch()) == ' ' || c == '\t')
  230.             ;
  231.     }
  232.  
  233.     else if(c=='h') {
  234.         s[0] = c = getch();
  235.         if(c =='e') {          /* help - Print 'Help screen' */
  236.             s[0] = c = getch();
  237.             if(c =='l') {
  238.                 s[0] = c = getch();
  239.                 if(c =='p') {
  240.                     help();
  241.                 }
  242.                 else errorMSG();
  243.             }
  244.             else errorMSG();
  245.         }
  246.         else errorMSG();
  247.         while((s[0] = c = getch()) == ' ' || c == '\t')
  248.             ;
  249.     }
  250.     else if(c=='p') {
  251.         s[0] = c = getch();
  252.         if(c =='s') stackprint();       /* ps - Print current stack   */
  253.         else if(c=='d') dsprint();      /* pd - Print duplicate stack   */
  254.         else if(c=='o') {
  255.             s[0] = c = getch();
  256.             if(c=='w') {                /* pow - pow(x,y) function */
  257.                 op2 = pop();
  258.                 l = pow(pop(),op2);           //    pow(x,y)   x**y
  259.                 NOPOP=0;
  260.                 push(l);                /* push to stack here */
  261.             }
  262.             else errorMSG();
  263.         }
  264.         else if(c=='i') ungets(PI);      /* pi: put value of pi onto input */
  265.         else errorMSG();
  266.         while((s[0] = c = getch()) == ' ' || c == '\t') // Skip spaces and tabs
  267.             ;
  268.     }
  269.     else if(c=='s') {
  270.         s[0] = c = getch();
  271.         if(c =='w') swaptop();          /* sw - Swap top two elements in current stack */
  272.         else if(c=='i') {
  273.             s[0] = c = getch();
  274.             if(c=='n') {                /* sin - sin(x) function */
  275.                 l = sin(pop());
  276.                 NOPOP=0;
  277.                 push(l);                /* push to stack here */
  278.             }
  279.             else errorMSG();
  280.         }
  281.         else if(c=='q') {
  282.             s[0] = c = getch();
  283.             if(c=='r') {                /* sqrt - sqrt(x) function */
  284.                 s[0] = c = getch();
  285.                 if(c=='t') {
  286.                     l = sqrt(pop());
  287.                     NOPOP=0;
  288.                     push(l);                /* push to stack here */
  289.                 }
  290.                 else errorMSG();
  291.             }
  292.             else errorMSG();
  293.         }
  294.         else errorMSG();
  295.         while((s[0] = c = getch()) == ' ' || c == '\t')
  296.             ;
  297.     }
  298.     else if(isalpha(c) && islower(c)) errorMSG();
  299.     }  /* End of do while*/
  300.     while(isalpha(c) && islower(c));
  301.     s[0] = c;
  302.     s[1] = '\0';
  303.     if(!isdigit(c) && c != '.' && c != '-')
  304.         return c;      /* Not a number          */
  305.     i = 0;
  306.     if(c == '-'){      /* collect fraction part */
  307.         NOPOP=0;
  308.         if(!isdigit(s[++i] = c = getch())) {
  309.            
  310.             ungetch(c);  // put into buffer (eg 4 4 * help
  311.             return '-';
  312.         }
  313.     }
  314.  
  315.     if(isdigit(c))    /* collect integer part  */
  316.         while(isdigit(s[++i] = c = getch()))
  317.             ;
  318.     if(c == '.')      /* collect fraction part */
  319.         while(isdigit(s[++i] = c = getch()))
  320.             ;
  321.     s[i] = '\0';
  322.     ungetch(c);
  323.     return NUMBER;
  324. }
  325.  
  326. /* push: push f onto value stack    */
  327. void push(double f)
  328. {
  329.  
  330.     if(sp < MAXVAL) {
  331.         val[sp++] = f;     // Add item as stack[sp] then increment sp
  332.     }
  333.     else
  334.         printf("error: stack full, cant push %g\n", f);
  335. }
  336.  
  337. /* pop: pop and return top value from stack */
  338. double pop(void)
  339. {
  340.     if(sp > 0) {
  341.         if(NOPOP==0) return val[--sp];   // return last item in stack first decrementing sp
  342.         else NOPOP=0;
  343.     }
  344.     else {
  345.         if(NOPOP==0) {
  346.             printf("error: stack empty\n");
  347.             return 0.0;
  348.         }
  349.         else NOPOP=0;
  350.     }
  351. }
  352.  
  353. /* get a (possibly pushed-back) character */
  354. int getch(void)
  355. {
  356.     return (bufp > 0) ? buf[--bufp] : getchar();  
  357. }
  358.  
  359. /* push character back on input */
  360. void ungetch(int c)
  361. {
  362.     if(bufp >= BUFSIZE)
  363.         printf("ungetch: too many characters\n");
  364.     else
  365.         buf[bufp++] = c;  // Add character to buffer and increment bufp
  366. }
  367.  
  368. /* ////////////// COMMAND FUNCTIONS ////////////// */
  369.  
  370. /* ungets: push a whole string onto input */
  371. void ungets(char s[])
  372. {
  373.     int len = strlen(s);
  374.  
  375.     while(len>0)
  376.         ungetch(s[--len]);
  377. }
  378.  
  379.  
  380. /* clearstack: Clear current stack  */
  381. void clearstack(void)
  382. {
  383.     sp=0;
  384.     puts("Stack cleared");
  385.     NOPOP=1;
  386. }
  387.  
  388. /* cleardupl: Clear duplicate stack */
  389. void cleardupl(void)
  390. {
  391.     dss=0;
  392.     puts("Duplicate stack cleared");
  393.     NOPOP=1;
  394. }
  395.  
  396. /* stackprint: print out current stack */
  397. void stackprint(void)
  398. {
  399.     int spp = sp;
  400.  
  401.     if(spp<=0) printf("error: stack empty\n");
  402.     else {
  403.         printf("--Top of current stack--\n");
  404.         while(spp>sp-2)                    // Note > 0 to print full stack
  405.             printf("%9g\n", val[--spp]);   // print last item in stack
  406.         printf("-------------\n");
  407.     }
  408.     NOPOP=1;
  409. }
  410.  
  411. /* dsprint: print out the duplicate stack top down */
  412. void dsprint(void)
  413. {
  414.     int spp = dss;
  415.  
  416.     if(spp<=0) printf("error: duplicate stack empty\n");
  417.     else {
  418.         printf("--duplicate stack--\n");
  419.         while(spp>0)                    // Note > 0 to print full stack
  420.             printf("%9g\n", dupval[--spp]);   // print last item in stack
  421.         printf("--end of duplicate stack --\n");
  422.     }
  423.     NOPOP=1;
  424. }
  425.  
  426. /* duplstack: make duplicate of the current stack */
  427. void duplstack(void)
  428. {
  429.     dss=0;
  430.  
  431.     if(sp<=0) printf("error: can't duplicate, stack is empty\n");
  432.     else {
  433.         while(dss<sp) {
  434.             dupval[dss] = val[dss];  
  435.             dss++;
  436.         }
  437.     puts("Duplicate stack created");
  438.     }
  439.     NOPOP=1;
  440. }
  441.  
  442. /* swaptop: Swap top two elements of stack */
  443. void swaptop(void)
  444. {
  445.     double temp;
  446.  
  447.     if(sp<=0) printf("error: stack empty\n");
  448.     else if(sp==1) printf("error: \n");
  449.     else {
  450.         temp = val[sp-1];
  451.         val[sp-1]=val[sp-2];
  452.         val[sp-2]=temp;
  453.         puts("Top two elements of stack swapped");
  454.     }
  455.     NOPOP=1;
  456. }
  457.  
  458. /* help: Print out help on available commands */
  459. void help(void)
  460. {
  461.     puts("------------------------------");
  462.     puts("Help: Commands");
  463.     puts("cs   - Clear current stack");
  464.     puts("cd   - Clear duplicate stack");
  465.     puts("ps   - Print current stack");
  466.     puts("pd   - Print duplicate stack");
  467.     puts("sw   - Swap top two elements in current stack");
  468.     puts("du   - Make duplicate of current stack");
  469.     puts("help - Print this 'Help screen'");
  470.     puts("------------------------------");
  471.     puts("Help: Functions");
  472.     puts("pi - add the value of pi to the input line");
  473.     puts("x cos");
  474.     puts("x exp");
  475.     puts("x y pow");
  476.     puts("x sin");
  477.     puts("x sqrt");
  478.     puts("------------------------------");
  479.     NOPOP=1;
  480. }
Advertisement
Add Comment
Please, Sign In to add comment