mkv

calc.cpp

mkv
Sep 7th, 2015
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.03 KB | None | 0 0
  1. /* calc.cpp - simple weighted calculator
  2.  * Copyright (C) 2010  ed <irc.rizon.net>
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License, version 2, as
  6.  * published by the Free Software Foundation.
  7.  *
  8.  * You should have received a copy of the GNU General Public License along
  9.  * with this program; if not, please refer to the following URL:
  10.  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  11.  */
  12.  
  13.  
  14. /* CHANGELOG:
  15.  * 2010.08.21 11:40 - 2010.08.21 12:18 - parser completed
  16.  * 2010.08.21 12:18 - 2010.08.21 13:37 - calculation completed
  17.  * 2010.08.22 15:56 - 2010.08.22 16:02 - handle division by zero
  18.  * 2010.08.23 06:53 - 2010.08.23 06:55 - minor cleanup
  19.  * 2010.08.26 09:54 - 2010.08.26 09:57 - expression from arguments
  20.  */
  21.  
  22.  
  23. /* USER'S MANUAL
  24.  *
  25.  * Compile and run program
  26.  * Type in numbers and operators
  27.  *  - spaces are optional
  28.  * Hit enter
  29.  * Profit
  30.  */
  31.  
  32.  
  33. /* ed@neetbook:~$ nano calc.cpp; g++ -Wall -o calc calc.cpp && ./calc
  34.  * expr> 17.68 + 32.14 * 8.1284 / -5.17 * 4.825 - 192.326
  35.  *
  36.  * Parser output:
  37.  *   17.68 + 32.14 * 8.13 / -5.17 * 4.82 - 192.33
  38.  *
  39.  * Calculation output:
  40.  *           8.13  /        -5.17 =        -1.57
  41.  *          32.14  *        -1.57 =       -50.53
  42.  *         -50.53  *         4.82 =      -243.81
  43.  *        -243.81  -       192.33 =      -436.14
  44.  *          17.68  +      -436.14 =      -418.46
  45.  *
  46.  * Final answer: -418.459481
  47.  */
  48.  
  49.  
  50. #include <cstdlib>
  51. #include <stdio.h>
  52. #include <math.h>
  53.  
  54. const int OPC = 6;
  55. const int MAX = 9000;
  56. const char opc[OPC+1] = {
  57.     ' ', '^', '%',
  58.     '/', '*',
  59.     '-', '+' };
  60.  
  61. // The basic idea:
  62. // 1+2-3*4/5    - expression
  63. // 0 + - * / ND - opc
  64. // 0 1 2 3 4 -1 - o
  65. // 1 2 3 4 5 ND - v
  66. // ND = not defined
  67.  
  68. // In-depth on opc:
  69. // opc[1..6] operators
  70. // opc[   0] no-op (calculated)
  71. // opc[  -1] EOF
  72.  
  73. void dump(int max, int *o, double *v) {
  74.     for (int i=0; i<max; i++) {
  75.         if (o[i]<0) fprintf(stderr, "\nSEMANTICAL ERROR\n");
  76.         printf("%c %1.2f ", opc[o[i]], v[i]);
  77.     }
  78.     putc('\n',stdout);
  79. }
  80. bool compute(int max, int *o, double *v, int op, bool verbose) {
  81.  
  82.     int i=0, j=0;
  83.  
  84.     // Scan for the operator we're looking for
  85.     for (i=0; i<max; i++) {
  86.  
  87.         // Is this it?
  88.         if (o[i]==op) {
  89.  
  90.             // Yup. Look for closest uncomputed number...
  91.             for (j=i-1; j>=0; j--) {
  92.  
  93.                 // Does this number have an operator?
  94.                 if (o[j]>0) break;
  95.                 // ...if so, we have the correct value of j.
  96.             }
  97.  
  98.             // Default back to root if no other options
  99.             if (j<0) j=0;
  100.  
  101.             // NOTE: at this point, opc[o[i]]==opc[op]
  102.             if (verbose) printf(
  103.                 "  %12.2f  %c %12.2f = ",
  104.                 v[j], opc[op], v[i]);
  105.  
  106.             // Check for division by zero
  107.             if (v[i] == 0 && (
  108.                 opc[op]=='/' ||
  109.                 opc[op]=='%'))
  110.                 return false;
  111.  
  112.             // Do the actual calculation
  113.                  if (opc[op]=='+') v[j] += v[i];
  114.             else if (opc[op]=='-') v[j] -= v[i];
  115.             else if (opc[op]=='*') v[j] *= v[i];
  116.             else if (opc[op]=='/') v[j] /= v[i];
  117.             else if (opc[op]=='^') pow(v[j], v[i]);
  118.             else if (opc[op]=='%') v[j] = (int)v[j] % (int)v[i];
  119.             o[i] = 0; //nothing to see here
  120.  
  121.             if (verbose) printf("%12.2f\n", v[j]);
  122.         }
  123.     }
  124.     return true;
  125. }
  126. int main(int argc, char **argv) {
  127.  
  128.     char *arg = (char *)"\0";
  129.     if (argc>1) arg = argv[1];
  130.  
  131.     // Verbose? Default yes; "n" disables
  132.     bool verbose = !(arg[0]=='n');
  133.     if (!verbose) arg++;
  134.  
  135.     // Expression from argument?
  136.     bool farg = arg[0]!='\0';
  137.  
  138.     // Expression management
  139.     int max;        //itemcount
  140.     int o[MAX];     //operator
  141.     double v[MAX];  //value
  142.     max = -1;
  143.  
  144.     // Vars for STDIN parsing
  145.     int i,j;        //indice/offset
  146.     char c;         //stdin buffer
  147.     int frac;       //fraction
  148.     bool neg;       //v*=-1
  149.     i=j=c=frac=0;   //clear
  150.     neg=false;
  151.  
  152.     if(verbose) printf("expr> ");
  153.     while (i<MAX && max<0) {
  154.  
  155.         if (farg) {c=arg[0];arg++;}
  156.         else scanf("%c",&c);
  157.  
  158.         // Parse digits
  159.         if (c >= '0' &&
  160.             c <= '9') {
  161.             c -= '0';
  162.  
  163.             // Integer
  164.             if (frac<1) {
  165.                 v[i] *= 10;
  166.                 v[i] += c;
  167.  
  168.             // Floating point
  169.             } else {
  170.                 frac *= 10;
  171.                 v[i] += c/1.0/frac;
  172.             }
  173.  
  174.         // Set floating point
  175.         } else if (c=='.' || c==',') {
  176.             frac = 1;
  177.  
  178.         // End of input
  179.         } else if (c=='\n' || c=='\0') {
  180.             i++;        //1-based
  181.             max  = i;   //setmax
  182.             o[i] =-1;   //eof
  183.  
  184.         // Operator?
  185.         } else if (c!=' '){
  186.  
  187.             // Check if it's a value negation
  188.             if (c=='-' && v[i]==0) {
  189.                 neg = true;
  190.  
  191.             } else {
  192.                 if(neg) v[i]*=-1;
  193.                 neg=false;
  194.                 frac=0;
  195.                 i++;
  196.  
  197.                 // Scan for operator
  198.                 for (j=1; j<=OPC; j++) {
  199.                     if (c==opc[j]) o[i]=j;
  200.                 }
  201.  
  202.                 // Invalid input
  203.                 if (o[i]<1) {
  204.                     fprintf(stderr, "\nPARSER ERROR\n");
  205.                     return 1;
  206.                 }
  207.             }
  208.         }
  209.     }
  210.  
  211.     if (verbose) {
  212.         printf("\nParser output:\n");
  213.         dump(max,o,v);
  214.         printf("\nCalculation output:\n");
  215.     }
  216.  
  217.     // Do calculations in decreasing weight
  218.     for (i=1; i<=OPC; i++) {
  219.         if (!compute(max,o,v,i,verbose)) {
  220.             fflush(stdout);
  221.             fprintf(stderr, "\nILLEGAL ARITHMETIC OPERATION\n");
  222.             return 1;
  223.         }
  224.     }
  225.  
  226.     if (!verbose) printf("%f\n", v[0]);
  227.     else printf("\nFinal answer: %f\n", v[0]);
  228.     return 0;
  229. }
Advertisement
Add Comment
Please, Sign In to add comment