Advertisement
Ae_Mc

My calc implementation

Dec 16th, 2019
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.91 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <math.h>
  6.  
  7. #define safefree(var) free(var); \
  8.     var = NULL;
  9. #define OP_MAX_PRORITY 2
  10.  
  11. typedef enum {
  12.     add, mul, power, reminder,
  13.     sub, divide, root
  14. } operation_type;
  15.  
  16. typedef struct operation {
  17.     operation_type op;
  18.     double *lnum, *rnum;
  19.     int priority;
  20.     struct operation *next;
  21. } operation;
  22.  
  23. double evop(operation_type op, double lnum, double rnum) {
  24.     switch(op) {
  25.         case add:
  26.             return lnum + rnum;
  27.         case sub:
  28.             return lnum - rnum;
  29.         case mul:
  30.             return lnum * rnum;
  31.         case divide:
  32.             return lnum / rnum;
  33.         case power:
  34.             return pow(lnum, rnum);
  35.         case root:
  36.             return pow(rnum, 1.0/lnum);
  37.         case reminder:
  38.             return lnum - (long) lnum / (long) rnum * (long) rnum;
  39.     }
  40. }
  41.  
  42. void ev(operation *optree) {
  43.     if (optree -> next != NULL) {
  44.         if (optree -> next -> priority > optree -> priority) {
  45.             ev(optree -> next);
  46.             *optree -> lnum = evop(optree -> op, *optree -> lnum, *optree -> rnum);
  47.         } else {
  48.             *optree -> rnum = evop(optree -> op, *optree -> lnum, *optree -> rnum);
  49.             ev(optree -> next);
  50.             *optree -> lnum = *optree -> rnum;
  51.         }
  52.         safefree(optree -> rnum);
  53.         safefree(optree -> next);
  54.     }
  55. }
  56.  
  57. int main(int argc, char **argv) {
  58.     char *exprstr, *exprptr;
  59.     if (argc > 1) {
  60.         int exprstrlen = 0;
  61.         exprstr = malloc(0);
  62.         exprptr = exprstr;
  63.         for (int i = 1; i < argc; i++) {
  64.             exprstrlen += strlen(argv[i]);
  65.             exprstr = (char*) realloc(exprstr, exprstrlen + i);
  66.             strcpy(exprptr, argv[i]);
  67.             exprptr = exprstr + exprstrlen + i;
  68.             *(exprptr - 1) = ' ';
  69.         }
  70.         *(exprptr - 1) = 0;
  71.     } else {
  72.         exprstr = malloc(100);
  73.         if(!scanf("%100[^\n]", exprstr)) {
  74.             fprintf(stderr, "Error reading expression!\n");
  75.             return -1;
  76.         }
  77.     }
  78.     exprptr = exprstr;
  79.  
  80.     if (exprstr) {
  81.         char *end = strlen(exprstr) + exprstr;
  82.         int curprior = 0;  // Current operation priority
  83.         double result;
  84.         operation *opptr, *optree = malloc(sizeof(operation));
  85.         opptr = optree;
  86.         optree -> lnum = &result;
  87.         optree -> next = NULL;
  88.  
  89.         while(exprptr < end) {
  90.         // Skip spaces and parentheses
  91.         while(exprptr < end && (isspace(*exprptr) || *exprptr == '('))
  92.             if (*exprptr++ == '(')
  93.                 curprior += OP_MAX_PRORITY + 1;
  94.  
  95.             opptr -> rnum = malloc(sizeof(double));
  96.             sscanf(exprptr, "%lf", opptr -> lnum);
  97.  
  98.             // Move pointer to symbol after number
  99.             if (*exprptr == '-') exprptr++;
  100.             exprptr += strspn(exprptr, ".0123456789");
  101.  
  102.             // Skip spaces and parentheses
  103.             while(exprptr < end && (isspace(*exprptr) || *exprptr == '(' || *exprptr == ')'))
  104.                 if (*exprptr++ == '(')
  105.                     curprior += OP_MAX_PRORITY + 1;
  106.                 else if (*(exprptr - 1) == ')')
  107.                     curprior -= OP_MAX_PRORITY + 1;
  108.  
  109.             // If end of string
  110.             if (exprptr == end)
  111.                 break;
  112.  
  113.             char op;
  114.             exprptr += sscanf(exprptr, "%c", &op);
  115.             switch (op) {
  116.                 case '+':
  117.                     opptr -> op = add;
  118.                     opptr -> priority = curprior;
  119.                     break;
  120.                 case '-':
  121.                     opptr -> op = sub;
  122.                     opptr -> priority = curprior;
  123.                     break;
  124.                 case '*':
  125.                     opptr -> op = mul;
  126.                     opptr -> priority = curprior + 1;
  127.                     break;
  128.                 case ':':
  129.                 case '/':
  130.                     opptr -> op = divide;
  131.                     opptr -> priority = curprior + 1;
  132.                     break;
  133.                 case '%':
  134.                     opptr -> op = reminder;
  135.                     opptr -> priority = curprior + 1;
  136.                     break;
  137.                 case 'p':
  138.                 case '^':
  139.                     opptr -> op = power;
  140.                     opptr -> priority = curprior + 2;
  141.                     break;
  142.                 case 'r':
  143.                     opptr -> op = root;
  144.                     opptr -> priority = curprior + 2;
  145.                     break;
  146.                 default:
  147.                     fprintf(stderr, "Error, operation %c is not allowed!\n", op);
  148.             }
  149.  
  150.             opptr -> next = malloc(sizeof(operation));
  151.             opptr -> next -> lnum = opptr -> rnum;
  152.             opptr -> next -> next = NULL;
  153.             opptr = opptr -> next;
  154.         }
  155.  
  156.         opptr = optree;
  157.         ev(optree);
  158.         printf("%lf\n", *optree -> lnum);
  159.         safefree(optree);
  160.     } else {
  161.         printf("Error reading input!\n");
  162.     }
  163.     free(exprstr);
  164.     return 0;
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement