[ create a new paste ] login | about

Link: http://codepad.org/CtoQXD3e    [ raw code | output | fork ]

C++, pasted on Nov 22:
#include <iostream>
#include <cctype>
#include <cstdlib>
double _calc(const char* s, const char** p, bool& e);
double calculate(char* s, bool& e);


int main(void){
	char  s[]  = "-(4)*10-(8+(7*(6/(5*(-4/(3/(2/(1/(((-8-(-2)*9)))-1)/2)/3)/4)/5))))+"\
	             "((10+20)/(-10+20-10+2*2+1)-1) + 500 * (1 / 123456789)";

	bool   err;
	double res = calculate(s, err);
	if(err)
		std::cout << res << std::endl;
	else
		std::cout << "error calculate!" << std::endl;
	return 0;
}


//вычисление мат-выражений из строки
double calculate(char* s, bool& e){
	int   i;
	char* a, *b;
	const char* p = NULL;
	double      n = 0.0;

	for(i = 0, p = s; *p; ++p){
		if(*p == '(')
			++i;
		else if(*p == ')'){
			if(--i < 0)
				break;
		}
	}

	e = true;
	if(*s && !i){
		a = s;
		while(*a && !isspace(*a))
			++a;

		for(b = a; *a; *a = *(++b)){
			if(! isspace(*b))
				++a;
		}
		if(*s)
			n = _calc(s, &p, e);
		else
			e = false;
	} else
		e = false;
	return n;
}

// рекурсивное вычисление мат-выражений из строки
double  _calc(const char* s, const char** p, bool& e){
	int    neg;
	char   c, c1;
	char*  i;
	const char* o;
	double k, v, n = 0.0;

	if((*s == '(') || (*s == '-' && *(s + 1) == '(')){
		neg = (*s == '-');
		n   = _calc(s + (1 + neg), &o, e);
		if(! e)
			return 0.0;
		s = o;
		if(neg)
			n = 0.0 - n;
	} else {
		n = strtod(s, &i);
		if(s == i){
			e = false;
			return 0.0;
		}
		s = i;
	}

	while(*s && (*s != ')')){
		c = *s++;
		if(! *s){
			e = false;
			return 0.0;
		}

		if(*s == '('){
			k = _calc(s + 1, &o, e);
			if(! e)
				return 0.0;
			s = o;
		} else {
			k = strtod(s, &i);
			if(s == i){
				e = false;
				return 0.0;
			}
			s = i;
		}

		switch(c){
		case '*':
			n *= k;
			break;
		case '/':
			if(k == 0.0){
				e = false;
				return 0.0;
			}
			n /= k;
			break;
		case '+':
		case '-':

			if((*s == '*') || (*s == '/')) {
				v = k;
				while(*s && (*s != ')')) {
					c1 = *s;
					if((c1 == '+') || (c1 == '-'))
						break;
					
					++s;
					if(*s == '('){
						k = _calc(s + 1, &o, e);
						if(! e)
							return 0.0;
						s = o;
					} else {
						k = strtod(s, &i);
						if(s == i){
							e = false;
							return 0.0;
						}
						s = i;
					}

					if(c1 == '/') {
						if(k == 0.0){
							e = false;
							return 0.0;
						}
						v /= k;
					} else if(c1 == '*')
						v *= k;
				}
				k = v;
			}

			if(c == '+')
				n += k;
			else if(c == '-')
				n -= k;

			if(*s == ')'){
				*p = s + 1;
				return n;
			}
			break;
		}
	}

	if(*s == ')')
		*p = s + 1;
	return n;
}


Output:
1
-80.8


Create a new paste based on this one


Comments: