C++表达式计算类示例

来源:互联网 发布:淘宝上钻要多少销量 编辑:程序博客网 时间:2024/05/01 06:37
// 程序基于C++之父的表达式计算例子改版为字符串流计算
#ifndef __EXPR__CALC__H__#define __EXPR__CALC__H__#include <iostream>#include <map>#include <string>#include <sstream>enum Token_value{NAME,       NUMBER,      END,PLUS='+',   MINUS='-',   MUL='*', DIV='/',PRINT=';',  ASSIGN='=',  LP='(',RP=')'};class ExprCalc{public:ExprCalc() : curr_tok(PRINT),no_of_errors(0) {}~ExprCalc(){ ss.clear(); table.clear(); }void operator << (const std::string &exp);void set(const std::string &var, double val);void set_table(std::map<std::string,double> &tab);double calc();bool get_error();private:Token_value get_token();double term(bool get);double expr(bool get);double prim(bool get);double error(const std::string& s);private:std::map<std::string,double> table;std::stringstream ss;std::string string_value;double number_value;int no_of_errors;Token_value curr_tok;};#endif 


#include "stdafx.h"#include "ExprCalc.h"Token_value ExprCalc::get_token(){char ch;do{if(!ss.get(ch))return curr_tok = END;}while(ch!='\n' && isspace(ch));switch(ch){case ';':case '\n':return curr_tok = PRINT;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 '.':ss.putback(ch);ss>>number_value;return curr_tok = NUMBER;default:if(isalpha(ch)){string_value = ch;while(ss.get(ch) && isalnum(ch))string_value.push_back(ch);ss.putback(ch);return curr_tok = NAME;}error("非法变量名");return curr_tok = PRINT;}}double ExprCalc::term(bool get){double left = prim(get);for(;;){switch(curr_tok){case MUL:left *= prim(true);break;case DIV:if(double d = prim(true)){left /= d;break;}return error("除以0溢出");default:return left;}}}double ExprCalc::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 ExprCalc::prim(bool get){if(get)get_token();switch(curr_tok){case NUMBER:{double v = number_value;get_token();return v;}case NAME:  {if(table.find(string_value) == table.end()){no_of_errors++;}double& v = table[string_value];if(get_token() == ASSIGN){v = expr(true);}return v;}case MINUS: {return -prim(true);}case LP:    {double e = expr(true);if(curr_tok != RP){return error("没有匹配右括号");}get_token();return e;}default:return error("初等项异常");}}double ExprCalc::error(const std::string& s){no_of_errors++;printf("错误: %s \n", s.c_str());return 1;}double ExprCalc::calc(){no_of_errors = 0;double ret = 0;while(!ss.eof()){get_token();if(curr_tok == END)break;if(curr_tok == PRINT)continue;ret = expr(false);}ss.clear();return ret;}void ExprCalc::set(const std::string &var, double val){if(table.find(var)!=table.end()){table.erase(var);}table[var] = val;}void ExprCalc::operator << (const std::string &exp){ss.clear();ss << exp;}void ExprCalc::set_table(std::map<std::string,double> &tab){table.clear();table.swap(tab);}bool ExprCalc::get_error(){return (no_of_errors != 0);}

#include "ExprCalc.h"int main(int argc, char *argv[]){ExprCalc ec;ec.set("a2",3);ec.set("b3",2.5);ec<<("a2*100 /b3");printf("%lf\n",ec.calc());ec<<(" a2 * ( b3 + 1 / 3 )");printf("%lf\n",ec.calc());ec.set("a2",4);ec<<("a2 * (b3 +1 /3) -1/3");printf("%lf\n",ec.calc());return 0;}


0 0