int evaluate(FILE *fout, const char *expr) { //parse the expression tokenNode *infix = createTokenNode(); addAfterTokenNode(infix); if (!parse(expr, infix)) { fprintf(stderr, "Parsing failed\n"); return 0; } //a flag for the +, - int previsnum = 0; initOperPriority(); //calculate for (tokenNode *i = infix->next; i->token != NULL; i = i->next) { char *endptr = NULL; long long thisNumber = createNumber(i->token, &endptr); if (readNumErr) { fprintf(stderr, "Failed reading a number\n"); freeAllTokenNodes(infix); return 0; } if (endptr != i->token) { pushNum(createFraction(thisNumber, 1)); previsnum = 1; } else { char oper = i->token[0]; switch (oper) { case '_': pushNum(lastResult); previsnum = 1; break; case '(': pushOper(oper); previsnum = 0; break; case ')': if(!calculatingCycle()) { fprintf(stderr, "Calculating failed\n"); freeAllTokenNodes(infix); return 0; } //pop the ( popOper(); previsnum = 0; break; default: //dealing with the signs if (!previsnum) { if (oper == '+') { oper = 'P'; } else if (oper == '-') { oper = 'N'; } } //there is an operator at the top of the stack if (operNum) { //compare the priorities of oper and topOper if (operPriority[(int)oper] < operPriority[(int)getTopOper()]) { //pop all and calc if(!calculatingCycle()) { fprintf(stderr, "Calculating failed\n"); freeAllTokenNodes(infix); return 0; } pushOper(oper); } else if (oper != 'P' && oper != 'N' && operPriority[(int)oper] == operPriority[(int)getTopOper()]) { //pop one and calc to ensure the calulation is done l2r //the P and N (aka +, -) are done r2l if(!calculate()) { fprintf(stderr, "Calculating failed\n"); freeAllTokenNodes(infix); return 0; } pushOper(oper); } else { pushOper(oper); } //the operator stack is empty } else { pushOper(oper); } previsnum = 0; break; } } } //pop the left operators and calc if(!calculatingCycle()) { fprintf(stderr, "Calculating failed\n"); freeAllTokenNodes(infix); return 0; } //pop the result Fraction *result = NULL; switch (numNum) { case 0: fprintf(stderr, "Get no result\n"); freeAllTokenNodes(infix); return 0; case 1: result = popNum(); lastResult = *result; fprintf(fout, "%lld", result->numerator); if (result->denominator != 1) { fprintf(fout, "/%lld\n", result->denominator); } else { fputc('\n', fout); } break; default: fprintf(stderr, "Get multiple results\n"); freeAllTokenNodes(infix); return 0; } freeAllTokenNodes(infix); return 1; }
char * calc(char * exp) { Stack * num_stack = initStackNum(strlen(exp)); Stack * oper_stack = initStackOper(strlen(exp)); int i; int bool_num = 0; int bool_min = 0; int cursor; double res = 0; char ch; double numVal; char * num = calloc(strlen(exp), sizeof(char)); for (i = 0; i < strlen(exp); ++i) { if (exp[i] >= '0' && exp[i] <= '9' || exp[i] == '.') { if (bool_num == 0) { bool_num = 1; cursor = 0; } else { cursor++; } num[cursor] = exp[i]; num[cursor+1] = '\0'; } else if (exp[i] == '+' || exp[i] == '-') { if (bool_num == 1) { char oper = exp[i]; double number = atof(num); if (bool_min > 0) { bool_min = 0; number = -number; } if (getCursorOper() >= 0) { if (!topOper(oper_stack, &ch)) return NULL; if (ch == '*') { popOper(oper_stack, &ch); if (!popNum(num_stack, &numVal)) return NULL; number = numVal * number; } else if (ch == '/') { popOper(oper_stack, &ch); if (!popNum(num_stack, &numVal)) return NULL; number = numVal / number; } } if (oper == '-') { oper = '+'; bool_min = 1; } if (!pushNum(num_stack, number)) return NULL; int j; for (j = 0; j < cursor+1; ++j) { num[j] = '\0'; } bool_num = 0; if (!pushOper(oper_stack, oper)) return NULL; } else { return NULL; } } else if (exp[i] == '*' || exp[i] == '/') { if (bool_num == 1) { double number = atof(num); if (bool_min > 0) { bool_min = 0; number = -number; } if (getCursorOper() >= 0) { if (!topOper(oper_stack, &ch)) return NULL; if (ch == '*') { popOper(oper_stack, &ch); if (!popNum(num_stack, &numVal)) return NULL; number = numVal * number; } else if (ch == '/') { popOper(oper_stack, &ch); if (!popNum(num_stack, &numVal)) return NULL; number = numVal / number; } } if (!pushNum(num_stack, number)) return NULL; int j; for (j = 0; j < cursor+1; ++j) { num[j] = '\0'; } bool_num = 0; if (!pushOper(oper_stack, exp[i])) return NULL; } else { return NULL; } } else { return NULL; } if (i == strlen(exp) - 1) { if (strlen(num) > 0) { double number = atof(num); if (bool_min > 0) { bool_min = 0; number = -number; } if (getCursorOper() >= 0) { if (!topOper(oper_stack, &ch)) return NULL; if (ch == '*') { popOper(oper_stack, &ch); if (!popNum(num_stack, &numVal)) return NULL; number = numVal * number; } else if (ch == '/') { popOper(oper_stack, &ch); if (!popNum(num_stack, &numVal)) return NULL; number = numVal / number; } } if (!pushNum(num_stack, number)) return NULL; int j; for (j = 0; j < cursor+1; ++j) { num[j] = '\0'; } bool_num = 0; } else { return NULL; } } } while (getCursorNum() > 0 && getCursorOper() >= 0) { double second; if(!popNum(num_stack, &second)) return NULL; double first; if(!popNum(num_stack, &first)) return NULL; char oper; if (!popOper(oper_stack, &oper)) return NULL; if (oper == '+') { double tmp_res = first + second; if(!pushNum(num_stack, tmp_res)) return NULL; } else if (oper == '-') { double tmp_res = first - second; if (!pushNum(num_stack, tmp_res)) return NULL; } } if (!popNum(num_stack, &res)) return NULL; char buff [100]; sprintf(buff,"%f", res); char * chres = malloc(sizeof(char)*strlen(buff)); strcpy(chres, buff); return chres; }