C++表达式计算类示例

// 程序基于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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值