Exemple #1
0
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;
}