借助堆栈实现的四则运算的源代码。输入一个字符串,可以计算值。
支持加减乘除、小数点、括号。
#include <string>
#include <iostream>
#include <stack>
#include <string>
#include <assert.h>
#include <exception>
using namespace std;
namespace utility
{
/// 异常定义类
class bad_expression : public std::exception
{
public:
bad_expression(){}
virtual const char * what() const{ return "bad expression"; }
};
namespace detail{
struct opdata
{
opdata(){}
opdata( char v ) : op(v), is_op(true){}
opdata( double v ) : val(v), is_op(false){}
bool is_op;
union{
double val;
char op;
};
};
inline double pop_value( std::stack<opdata>& op )
{
if( op.top().is_op ) throw bad_expression();
double c=op.top().val;
op.pop();
return c;
}
/// 弹出栈并计算,直到碰到 '(' 或者栈底
static void calculate( std::stack<opdata>& op, double& v, bool addsub=true )
{
while( !op.empty() ){
opdata o=op.top();
if( o.is_op ){
switch( o.op ){
case '(':
return;
case '+':
if( !addsub ) return; // 如果 addsub=false 不计算 +
op.pop();
v=pop_value(op)+v;
break;
case '-':
if( !addsub ) return; // 如果 addsub=false 不计算 -
op.pop();
v=pop_value(op)-v;
break;
case '*':
op.pop();
v=pop_value(op)*v;
break;
case '/':
op.pop();
v=pop_value(op)/v;
break;
case '.':
op.pop();
v=v / ( pow( 10, int( log10(v) )+1 ) +pop_value(op);
break;
default:
throw bad_expression();
}
}else{
if( v!=0 ) throw bad_expression();
v=o.val;
op.pop();
}
}
}
}
static double calculate( const std::string& expr )
{
using namespace detail;
//the operation value
std::stack< opdata > opv;
double v=0;
for( auto i=expr.cbegin(); i!=expr.cend(); ++i ){
char c=*i;
if( ( c>='0' ) && ( c<='9' ) ){
c=c-'0';
v=v*10+c;
}else if(')'== c){ // 计算
calculate( opv, v );
if( opv.top().op!='(' ) throw bad_expression();
opv.pop();
}else if( '('==c ){
opv.push( c );
}else if( '+'==c || '-'==c ){
calculate( opv, v );
opv.push(v);
opv.push( c );
v=0;
}else if( '*'==c || '/'==c ){
calculate( opv, v, false );
opv.push(v);
opv.push(c);
v=0;
}else if( '.'==c ){
opv.push(v);
opv.push(c);
v=0;
}else{
throw bad_expression();
}
}
calculate( opv, v );
return v;
}
};
测试: