Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
- #define safefree(var) free(var); \
- var = NULL;
- #define OP_MAX_PRORITY 2
- typedef enum {
- add, mul, power, reminder,
- sub, divide, root
- } operation_type;
- typedef struct operation {
- operation_type op;
- double *lnum, *rnum;
- int priority;
- struct operation *next;
- } operation;
- double evop(operation_type op, double lnum, double rnum) {
- switch(op) {
- case add:
- return lnum + rnum;
- case sub:
- return lnum - rnum;
- case mul:
- return lnum * rnum;
- case divide:
- return lnum / rnum;
- case power:
- return pow(lnum, rnum);
- case root:
- return pow(rnum, 1.0/lnum);
- case reminder:
- return lnum - (long) lnum / (long) rnum * (long) rnum;
- }
- }
- void ev(operation *optree) {
- if (optree -> next != NULL) {
- if (optree -> next -> priority > optree -> priority) {
- ev(optree -> next);
- *optree -> lnum = evop(optree -> op, *optree -> lnum, *optree -> rnum);
- } else {
- *optree -> rnum = evop(optree -> op, *optree -> lnum, *optree -> rnum);
- ev(optree -> next);
- *optree -> lnum = *optree -> rnum;
- }
- safefree(optree -> rnum);
- safefree(optree -> next);
- }
- }
- int main(int argc, char **argv) {
- char *exprstr, *exprptr;
- if (argc > 1) {
- int exprstrlen = 0;
- exprstr = malloc(0);
- exprptr = exprstr;
- for (int i = 1; i < argc; i++) {
- exprstrlen += strlen(argv[i]);
- exprstr = (char*) realloc(exprstr, exprstrlen + i);
- strcpy(exprptr, argv[i]);
- exprptr = exprstr + exprstrlen + i;
- *(exprptr - 1) = ' ';
- }
- *(exprptr - 1) = 0;
- } else {
- exprstr = malloc(100);
- if(!scanf("%100[^\n]", exprstr)) {
- fprintf(stderr, "Error reading expression!\n");
- return -1;
- }
- }
- exprptr = exprstr;
- if (exprstr) {
- char *end = strlen(exprstr) + exprstr;
- int curprior = 0; // Current operation priority
- double result;
- operation *opptr, *optree = malloc(sizeof(operation));
- opptr = optree;
- optree -> lnum = &result;
- optree -> next = NULL;
- while(exprptr < end) {
- // Skip spaces and parentheses
- while(exprptr < end && (isspace(*exprptr) || *exprptr == '('))
- if (*exprptr++ == '(')
- curprior += OP_MAX_PRORITY + 1;
- opptr -> rnum = malloc(sizeof(double));
- sscanf(exprptr, "%lf", opptr -> lnum);
- // Move pointer to symbol after number
- if (*exprptr == '-') exprptr++;
- exprptr += strspn(exprptr, ".0123456789");
- // Skip spaces and parentheses
- while(exprptr < end && (isspace(*exprptr) || *exprptr == '(' || *exprptr == ')'))
- if (*exprptr++ == '(')
- curprior += OP_MAX_PRORITY + 1;
- else if (*(exprptr - 1) == ')')
- curprior -= OP_MAX_PRORITY + 1;
- // If end of string
- if (exprptr == end)
- break;
- char op;
- exprptr += sscanf(exprptr, "%c", &op);
- switch (op) {
- case '+':
- opptr -> op = add;
- opptr -> priority = curprior;
- break;
- case '-':
- opptr -> op = sub;
- opptr -> priority = curprior;
- break;
- case '*':
- opptr -> op = mul;
- opptr -> priority = curprior + 1;
- break;
- case ':':
- case '/':
- opptr -> op = divide;
- opptr -> priority = curprior + 1;
- break;
- case '%':
- opptr -> op = reminder;
- opptr -> priority = curprior + 1;
- break;
- case 'p':
- case '^':
- opptr -> op = power;
- opptr -> priority = curprior + 2;
- break;
- case 'r':
- opptr -> op = root;
- opptr -> priority = curprior + 2;
- break;
- default:
- fprintf(stderr, "Error, operation %c is not allowed!\n", op);
- }
- opptr -> next = malloc(sizeof(operation));
- opptr -> next -> lnum = opptr -> rnum;
- opptr -> next -> next = NULL;
- opptr = opptr -> next;
- }
- opptr = optree;
- ev(optree);
- printf("%lf\n", *optree -> lnum);
- safefree(optree);
- } else {
- printf("Error reading input!\n");
- }
- free(exprstr);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement