Page 1 of 1

equation solver

Posted: Tue Nov 10, 2009 1:13 pm
by avansc
ugly and not clean, just what it is.

wont work if there are white spaces in equation.

h

Code: Select all

/*
 *  cMathExp.h
 *  objects
 *
 *  Created by avansc on 11/6/09.
 *  Copyright 2009 avansc. All rights reserved.
 *
 */

#ifndef _cMathExp_h
#define _cMathExp_h

class cMathExp
{
public:
	cMathExp();
	char *solve(char *data);
	void setPrecision(int x);

private:
	char *pGetExp();
	char *splitInner(char *data);
	char *splitInnerWithBraces(char *data);
	char *replace(const char *subject, const char *search, const char *replace);
	char *trigFunc(char *data, int f);
	int precision;
};

#endif
code

Code: Select all

/*
 *  cMathExp.cpp
 *  objects
 *
 *  Created by avansc on 11/6/09.
 *  Copyright 2009 avansc. All rights reserved.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "cMathExp.h"

cMathExp::cMathExp()
{
	this->precision = -1;
}

void cMathExp::setPrecision(int x)
{
	if(x <= 0)
	{
		this->precision = -1;
	}else if(x <= 10)
	{
		this->precision = x;
	}else{
		this->precision = 10;
	}

}

char *cMathExp::solve(char *data)
{

	printf("%s\n", data);
	
	char *test = (char*)malloc(sizeof(char)*strlen(data));
	test = strdup(data);
	test = strtok(test,  "^*/+-(");
	test = strtok(NULL, "^*/+-(");
	if(!test)
		return data;

	//////////// trig code ///////////
	char *trig[] = {"sin", "cos", "tan", "asin", "acos", "atan"};

	for(int a = 0;a < 6;a++)
	{
		if( (test =strstr(data, trig[a])))
		{
			char *f = (char*)malloc(sizeof(char)*strlen(test));
			f[0] = '\0';
			char *test2 = (char*)malloc(sizeof(char)*strlen(test));
			test2 = strdup(test);
			int count = 0;
			while(*test2)
			{	
				if(*test2 == ')')
				{
					count--;
					if(count == 0)
						break;
				}
				if(count > 0)
				{
					strncat(f, test2, 1);
				}
				if(*test2 == '(')
				{
					count++;
				}
				test2++;
			}
			test2[0] = '\0';
			strncat(test2, test, strlen(f)+5);
			return this->solve(this->replace(data, test2, this->trigFunc(this->solve(f),a)));
		}
	}
	//////////// end trig code ///////////
	
	//////////// braces /////////////
	if(strchr(data, '('))
	{
		return this->solve(this->replace(data,this->splitInnerWithBraces(data), solve(this->splitInner(data))));
	}
	//////////// end braces ///////////
	
	
	/////////// ^,multi,div,add,sub ///////////

	int mdcount = 0;
	char set[] = "1234567890.";
	char signset[] = "^*/+-";
	for(int a = 0;a < strlen(data);a++)
	{
		if(strchr(signset, data[a]))
		{
			mdcount++;
		}
	}
	
	if(mdcount > 1)
	{
		for(int a = 0;a < 5;a++)
		{
			int c1 = 0;
			
			char *numbers = (char*)malloc(sizeof(char)*strlen(data));
			numbers = strdup(data);
			
			char *ops = (char*)malloc(sizeof(char)*strlen(data));
			ops = strdup(data);
			
			ops = strtok(ops, set);
			
			while(ops)
			{
				if(*ops == signset[a])
				{
					char *temp_op = strdup(ops);
					numbers = strtok(numbers, signset);
					for(int b = 0;b < c1;b++)
					{
						numbers = strtok(NULL, signset);
					}
					//printf("%s%s%s\n", numbers, temp_op, strtok(NULL, signset));
					char *t1 = strdup(numbers);
					numbers = strtok(NULL,	signset);
					char *t2 = strdup(numbers);
					strcat(t1, strdup(temp_op));
					strcat(t1, strdup(t2));
					return strdup(this->solve(strdup(this->replace(data, strdup(t1), strdup(this->solve(strdup(t1)))))));;
				}
				ops = strtok(NULL, set);
				c1++;
			}
		}
	}
		
	///////// end multi & div /////////

	char **num = (char**)malloc(sizeof(char*)*2);
	num[0] = (char*)malloc(sizeof(char)*10);
	num[0][0] = '\0';
	
	char op;
	int count = 0;
	
	while(*data)
	{
		if(strchr(set, *data))
		{
			strncat(num[count], data, 1);
		}else {
			count++;
			num[count] = (char*)malloc(sizeof(char)*10);
			num[count][0] = '\0';
			op = *data;
		}

		data++;
	}
	
	float a = atof(num[0]);
	float b = atof(num[1]);
	
	
	float c = 0;
	if(op == '^')
	{
		c = pow(a,b);
	}else if(op == '*')
	{
		c = a * b;
	}else if(op == '/')
	{
		c = a / b;
	}else if(op == '+')
	{
		c = a + b;
	}else if(op == '-')
	{
		c = a - b;
	}
	
	char *alph = (char*)malloc(sizeof(char)*strlen(data)+11);
	sprintf(alph,"%0.10f",(float)c);
	
	alph[strlen(alph)-(10-this->precision)] = '\0'; 
	
	free(num[0]);
	free(num[1]);
	free(num);
	
	return alph;
}	

char *cMathExp::splitInner(char *data)
{
	char *ret = (char*)malloc(sizeof(char)*strlen(data));
	ret[0] = '\0';
	
	while(*data)
	{	
		if(*data == ')')
		{	
			return strdup(ret);
		}
		strncat(ret, data, 1);
		if(*data == '(')
		{	
			ret[0] = '\0';
		}
		data++;
	}
	return NULL;
}

char *cMathExp::splitInnerWithBraces(char *data)
{
	char *ret = (char*)malloc(sizeof(char)*strlen(data));
	ret[0] = '\0';
	
	while(*data)
	{	
		strncat(ret, data, 1);
		if(*data == '(')
		{	
			ret[0] = '\0';
			strncat(ret, data, 1);
		}
		if(*data == ')')
		{	
			return strdup(ret);
		}
		data++;
	}
	return NULL;
}

char *cMathExp::replace(const char *subject, const char *search, const char *replace)
{
		if (search == NULL || replace == NULL || subject == NULL) return NULL;
		if (strlen(search) == 0 || strlen(replace) == 0 || strlen(subject) == 0) return NULL;
		
		char *replaced = (char*)calloc(1, 1), *temp = NULL;
		char *p = (char*)subject, *p3 = (char*)subject, *p2;
		int  found = 0;
		
		while ( (p = strstr(p, search)) != NULL) {
			found = 1;
			temp = (char*)realloc(replaced, strlen(replaced) + (p - p3) + strlen(replace));
			if (temp == NULL) {
				free(replaced);
				return NULL;
			}
			replaced = temp;
			strncat(replaced, p - (p - p3), p - p3);
			strcat(replaced, replace);
			p3 = p + strlen(search);
			p += strlen(search);
			p2 = p;
		}
		
		if (found == 1) {
			if (strlen(p2) > 0) {
				temp = (char*)realloc(replaced, strlen(replaced) + strlen(p2) + 1);
				if (temp == NULL) {
					free(replaced);
					return NULL;
				}
				replaced = temp;
				strcat(replaced, p2);
			}
		} else {
			temp = (char*)realloc(replaced, strlen(subject) + 1);
			if (temp != NULL) {
				replaced = temp;
				strcpy(replaced, subject);
			}
		}
		return replaced;
}

char *cMathExp::trigFunc(char *data, int f)
{
	float a = atof(data);
	
	float c = 0;
	switch(f)
	{
		case 0 :
		{
			c = sin(a);
			break;
		}
		case 1 :
		{
			c = cos(a);
			break;
		}
		case 2 :
		{
			c = tan(a);
			break;
		}
		case 3 :
		{
			c = asin(a);
			break;
		}
		case 4 :
		{
			c = acos(a);
			break;
		}
		case 5 :
		{
			c = atan(a);
			break;
		}
	}
	
	char *alph = (char*)malloc(sizeof(char)*strlen(data));
	sprintf(alph,"%0.10f",(float)c);

	return alph;
}

Re: equation solver

Posted: Tue Nov 10, 2009 2:10 pm
by short
I really like this, and I learned a new command too haha:
temp = (char*)realloc(replaced, strlen(subject) + 1);
I had no idea there was a realloc command, and call me a geek but, I think its way cool the way it works. (looked it up)

Thank you for sharing!

Re: equation solver

Posted: Tue Nov 10, 2009 2:15 pm
by avansc
short wrote:I really like this, and I learned a new command too haha:
temp = (char*)realloc(replaced, strlen(subject) + 1);
I had no idea there was a realloc command, and call me a geek but, I think its way cool the way it works. (looked it up)

Thank you for sharing!
thanx, yeah its nice.. just note that i have not gone through that to make sure there are no leaks on anything. i dont think there are. but just not that was tinkered with to work, and barely looked at again.

Re: equation solver

Posted: Tue Nov 10, 2009 7:30 pm
by Falco Girgis
short wrote:I really like this, and I learned a new command too haha:
temp = (char*)realloc(replaced, strlen(subject) + 1);
I had no idea there was a realloc command, and call me a geek but, I think its way cool the way it works. (looked it up)

Thank you for sharing!
Don't use it too much, though. It fragments your heap to hell when you start having large amounts of small reallocations.