|
|
发表于 2006-4-24 21:45:56
|
显示全部楼层
see code below, may be help for you.
- #include<iostream>
- #include<map>
- #include<string>
- #include<cctype>
- #include<math.h>
- using namespace std;
- class expr;
- enum Token_value{
- SQRT,SIN,COS,
- NAME,NUMBER,END,
- PLUS='+',MINUS='-',MUL='*',DIV='/',
- PRINT=';',ASSIGN='=',LP='(',RP=')',MIN='^'
- };
- typedef double (*dfdp)(double);
- dfdp math[]={sqrt,sin,cos};
- int i;
- typedef Token_value (expr::*get_token_p_p)();
- get_token_p_p get_token_p;
- class expr{
- public:
- expr(const char* str);
- expr(void);
- void jisuan(void);
- double eval();
- void print(){}
- private:
- int line_no;
- string string_expr;
- double (*dfddp)(double,double);
- double number_value;
- string string_value;
- map<string,double> table;
- Token_value curr_tok;
- double my_expr(bool get);
- double term(bool get);
- double prim(bool get);
- double min(bool get);
- Token_value get_token(void);
- Token_value get_token_ios(void);
- double error(char *str);
- };
- expr::expr(void)
- {
- line_no=0;
- i=-1;
- number_value=0;
- table["pi"]=3.1415;
- table["e"]=2.718281;
- }
- expr::expr(const char* str)
- {
- string_expr=str;
- expr();
- }
- double expr::error(char *str)
- {
- cerr<<"line:"<<line_no<<" "<<str<<endl;
- return 1;
- }
- double expr::my_expr(bool get)
- {
- double left=term(get);
- for(;;)
- switch(curr_tok){
- case PLUS:
- left+=term(true);
- break;
- case MINUS:
- left-=term(true);
- break;
- default:
- return left;
- }
- }
- double expr::term(bool get)
- {
- double left=min(get);
- for(;;)
- switch(curr_tok){
- case MUL:
- left*=min(true);
- break;
- case DIV:
- if(double d=min(true)){
- left/=d;
- break;
- }
- return error("divide by 0");
- default:
- return left;
- }
- }
- double expr::min(bool get)
- {
- double left=prim(get);
- dfddp=pow;
- for(;;)
- {
- switch(curr_tok){
- case MIN:
- left=dfddp(left,prim(true));
- break;
- case SQRT:
- left=math[SQRT](left);
- (this->*get_token_p)();
- return left;
- case SIN:
- left=math[SIN](left);
- (this->*get_token_p)();
- return left;
- case COS:
- left=math[COS](left);
- (this->*get_token_p)();
- return left;
- default:
- return left;
- }
- }
- }
- double expr::prim(bool get)
- {
- if(get) (this->*get_token_p)();
- switch(curr_tok){
- case NUMBER:
- {
- double v=number_value;
- (this->*get_token_p)();
- return v;
- }
- case NAME:
- {
- if(strcmp(string_value.c_str(),"sqrt")==0)
- {
- (this->*get_token_p)();
- if(curr_tok!=LP) return error("(expected");
- double e=my_expr(true);
- if(curr_tok!=RP) return error(")expected");
- //get_token(); // delete RP;
- curr_tok=SQRT;
- return e;
- }
- else if(strcmp(string_value.c_str(),"sin")==0)
- {
- (this->*get_token_p)();
- if(curr_tok!=LP) return error("( expected");
- double e=my_expr(true);
- if(curr_tok!=RP) return error(")expected");
- curr_tok=SIN;
- return e;
- }
- else if(strcmp(string_value.c_str(),"cos")==0)
- {
- (this->*get_token_p)();
- if(curr_tok!=LP) return error("( expected");
- double e=my_expr(true);
- if(curr_tok!=RP) return error(")expected");
- curr_tok=COS;
- return e;
- }
- else {
- double& v=table[string_value];
- if((this->*get_token_p)()==ASSIGN)
- { line_no++; v=my_expr(true);}
- return v;
- }
- }
- case MINUS:
- return -prim(true);
- case LP:
- {
- double e=my_expr(true);
- if(curr_tok!=RP) return error(")expected");
- (this->*get_token_p)(); // delete RP;
- return e;
- }
- return error("primay expected");
- }
- }
- Token_value expr::get_token(void)
- {
- char ch=0;
- double power=1;
- number_value=0.0;
- do{
- if(!(ch=string_expr[++i])) return curr_tok=END;
- }while(ch!='\n' && isspace(ch));
- switch(ch){
- case 0:
- return curr_tok=END;
- case ';':
- case '*':
- case '/':
- case '+':
- case '-':
- case '(':
- case ')':
- case '=':
- case '^':
- return curr_tok=Token_value(ch);
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '.':
- //string_expr.putback(ch);
- while((isdigit((int)ch)))
- {
- number_value=number_value*10+(ch-'0');
- ch=string_expr[++i];
- }
- if(ch=='.')
- ch=string_expr[++i];
- while((isdigit((int)ch)))
- {
- number_value=number_value*10+(ch-'0');
- ch=string_expr[++i];
- power*=10;
- }
- i--;
- number_value=number_value/power;
- // cout<<number_value<<endl;
- return curr_tok=NUMBER;
- default:
- if(isalpha(ch)){
- string_value=ch;
- while((ch=string_expr[++i]) && isalnum(ch)) string_value.push_back(ch);
- i--;
- return curr_tok=NAME;
- }
- //error("bad token");
- return curr_tok=PRINT;
- }
- }
- Token_value expr::get_token_ios(void)
- {
- char ch=0;
- do{
- if(!cin.get(ch)) return curr_tok=END;
- }while(ch!='\n' && isspace(ch));
- switch(ch){
- case 0:
- return curr_tok=END;
- case ';':
- case '*':
- case '/':
- case '+':
- case '-':
- case '(':
- case ')':
- case '=':
- case '^':
- return curr_tok=Token_value(ch);
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '.':
- cin.putback(ch);
- cin>>number_value;
- return curr_tok=NUMBER;
- default:
- if(isalpha(ch)){
- string_value=ch;
- while(cin.get(ch) && isalnum(ch)) string_value.push_back(ch);
- cin.putback(ch);
- return curr_tok=NAME;
- }
- //error("bad token");
- return curr_tok=PRINT;
- }
- }
- void expr::jisuan(void)
- {
- get_token_p=&expr::get_token_ios;
- while(cin){
- (this->*get_token_p)();
- if(curr_tok==END)break;
- if(curr_tok==PRINT)continue;
- cout<<my_expr(false)<<'\n';
- // cout<<number_value<<endl;
- }
- //return 0;
- }
- double expr::eval(void)
- {
- get_token_p=&expr::get_token;
- //while(string_expr){
- (this->*get_token_p)();
- //if(curr_tok==END)break;
- //if(curr_tok==PRINT)continue;
- return my_expr(false);
- // cout<<number_value<<endl;
- // }
- //return 0;
- }
- int main(void)
- { /*
- expr x("123/3+123*4-3");
- cout<<"x="<<x.eval()<<"\n";
- x.print();
- */
- expr a("1+3+9/3");
- cout<<a.eval()<<endl;
- a.jisuan();
- }
复制代码 |
|