ok, I need to sleep, if you want to play with this tonight, here is the full source for that console app. seems like I'm going to have to pre process the input infix data and find unary '-'s and give them some specal tolken. then add a whole new class of opperators that only have one operand, I was going to need to do this eventualy to suport sin, cos, (ect).
sleepy time :)
#include
#include
#include
#include
#include
using namespace std;
struct ship{
float a;
};
class variable{
public:
virtual float value(ship*shipp=NULL) = 0;
};
class constant:public variable{
float val;
public:
constant(float in):val(in){};
float value(ship*shipp=NULL){return val;};
};
class operate:public variable{
protected:
variable *operand1, *operand2;
public:
virtual float value(ship*shipp=NULL) = 0;
operate(variable*op1, variable*op2){operand1 = op1; operand2 = op2;}
~operate(){if(operand1)delete operand1; if(operand2)delete operand2;}
};
class add:public operate{
public:
add(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) + operand2->value(shipp);}
};
class sub:public operate{
public:
sub(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) - operand2->value(shipp);};
};
class divide:public operate{
public:
divide(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) / operand2->value(shipp);};
};
class power:public operate{
public:
power(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return(float)pow(operand1->value(shipp), operand2->value(shipp));};
};
class mult:public operate{
public:
mult(variable*op1, variable*op2):operate(op1,op2){}
float value(ship*shipp=NULL){return operand1->value(shipp) * operand2->value(shipp);};
};
class expression:public variable{
int n_var; //number of variables in the expression
variable *head; //the head of the expression
void postfix(string&);
variable* parse_next(char*&);
variable* get_ship_variable(char**);
public:
expression(char*);
~expression(){for(int i = 0;i float value(ship*shipp=NULL);
};
/*
variable* con = new constant(1.0f);
variable* op = new add(con,con);
*/
expression::expression(char* in_str):n_var(0),head(NULL){
string str = in_str;
postfix(str);
char* is = new char[str.length()+1];
char* os = is;
strcpy(is, str.c_str());
head = parse_next(is);
delete[]os;
}
variable* expression::parse_next(char*&in_str){
//kill any noise
while((*in_str == ' ' || *in_str == ' ') && *in_str != char(0))in_str++;
char ship_idnt[] = "ship:";
char op_char[] = "+-/*^";
if(!strcmp(in_str,ship_idnt)){
(*in_str)+=strlen(ship_idnt);
//it's a ship variable
return get_ship_variable(&in_str);
}else{
//it's a constant, or an opporateor
if(strchr(op_char, *in_str) && *(in_str+1) == ','){
//it must be an operator
char o = *in_str++;
if(*in_str == ',')in_str++;
variable*a = parse_next(in_str);
variable*b = parse_next(in_str);
switch(o){
case '+':return new add(a,b);
case '-':return new sub(a,b);
case '*':return new mult(a,b);
case '/':return new divide(a,b);
case '^':return new power(a,b);
}
}else{
//it must be a constant
char *str = in_str;
while(*(in_str) != ',' && *in_str != 0)in_str++;
if(*in_str == ',')in_str++;
return new constant(atof(str));
}
}
return NULL;
}
variable* expression::get_ship_variable(char**){
return new constant(0.0f);
}
inline int get_value(char c){
switch(c){
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
default:return -1;
}
}
bool is_value(char c){
if(c >= '0' && c <= '9')return true;
if(c == '.')return true;
return false;
}
void fix_implied_mult(string &str){
for(int i = 1; i< str.length(); i++){
if(str[i] == '('){
if(!get_value(str[i-1]))
str.insert(i,"*");
}
}
}
void reverse(string&s){
string out = "";
int l = s.length();
string temp = "";
for(int i = 0; i for(i; i temp += s[i];
if(!is_value(s[i]) || !is_value(s[i+1]))break;
}
out.insert(0,temp);
temp = "";
}
s = out;
}
void expression::postfix(string& str){
string s = str;
fix_implied_mult(s);
stack op_stack;
string out;
reverse(s);
int i = 0;
while(s[i]){
if(is_value(s[i])){
int sidx = i;
while(is_value(s[i]))out+=s[i++];
if(s[i] == '-' && (s[i+1] == 0 || s[i+1] == '(' || get_value(s[i+1]) != -1)){
out+="-";
i++;
}
out+=',';
}else if(s[i] == ')'){
op_stack.push(s[i++]);
}else if(s[i] == '('){
while(op_stack.top() != ')'){
out+=op_stack.top();
op_stack.pop();
out+=',';
}
op_stack.pop();
i++;
}else{
int v = get_value(s[i]);
if(v){
//it's an opperator
if(op_stack.empty() || op_stack.top() == ')' || get_value(op_stack.top()) <= v){
op_stack.push(s[i++]);
}else{
while(!op_stack.empty() && get_value(op_stack.top()) > v){
out+=op_stack.top();
op_stack.pop();
out+=',';
}
op_stack.push(s[i++]);
}
}
}
}
while(!op_stack.empty()){out+=op_stack.top(); op_stack.pop(); out+=',';}
out.resize(out.length()-1);
reverse(out);
str = out;
}
float expression::value(ship*shipp){
return head->value(shipp);
}
void main(){
string str = "";
// string str = "(1+2)*(3+4)*(5+6)";
// string str = "1+(2+3*4^(5-3)-7)*3";
// string str = "1+2+3*4^5-6-7*8";
// string str = "1+2*3+4";
// string str = "1*(2+3)";
// string str = "2*3/(2-1)+5*(4-1)";
// string str = "49*49-49";
cout << "enter an expression or type exit to do so\n";
cin >> str;
while(str!="exit"){
char test[512];
strcpy(test, str.c_str());
expression exp(test);
// cout << pow(4.0f,5.0f);
cout << "\n" << str << " = " << exp.value() << "\nif this is not corect, please tell me and provide the expression you entered\n\nenter another expression or type exit to do so:\n";
str = "";
cin >> str;
}
cout << "thank you for testing me";
}