C++实现表达式求值

刚学C++,一个表达式求值的问题,困扰我好久,昨天终于搞掂了,发上来给在家分享下哈哈!

#include "stdafx.h"
#include "Constant.h"
#include<iostream>
#include"MathCalc.h"
#include<string.h>
#include<ctype.h>
#include<math.h>
#include <stdlib.h>
using namespace std;


int MathCalc::aiPriority[9][9]={
 {  1,  1, -1, -1, -1, -1,  1,  1,  -1},
 {  1,  1, -1, -1, -1, -1,  1,  1,  -1},
 {  1,  1,  1,  1, -1, -1,  1,  1,  -1},
 {  1,  1,  1,  1, -1, -1,  1,  1,  -1},
 {  1,  1,  1,  1, -1, -1,  1,  1,  -1},
 { -1, -1, -1, -1, -1, -1,  0,255,  -1},
 {  1,  1,  1,  1,  1,255,  1,  1,   1},
 { -1, -1, -1, -1, -1, -1, -1,  0,  -1},
 {  1,  1,  1,  1,  1, -1,  1,  1,  -1}
};
  
/*运算符优先级表
=========================================
*  + - * / ^ ( )   #  @ 
* + > > < < < < >   >  <
* - > > < < < < > >  <
* * > > > > < < > >  <
* / > > > > < < > >  <
* ^ > > > > < < > >  <
* ( < < < < < < = <  
* ) > > > > >  > >  >
* # < < < < < < < =  <
 @ > > > > > < > >  <

*=========================================
*/

char * MathCalc::ErrMsg[5] = {
  "None Error.",
  "There is not expression for calculating.",
  "Invalid usage of operator.",
  "Lack operator for calculating.",
  "Lack argument for calculating."
};


MathCalc::MathCalc(){

 m_StackOptr = new Stack();
 
 m_StackOpnd = new Stack();
}

MathCalc::~MathCalc(){
 delete m_strExpression;
 delete m_StackOptr;
 delete m_StackOpnd;
}


char * MathCalc::getCalc(){
 return m_strExpression;
}

int MathCalc::GetErrCode(){
 return m_ErrCode;
}

char * MathCalc::GetErrMsg(){
 return MathCalc::ErrMsg[-m_ErrCode];
}

void MathCalc::setStackOptr(Stack * a_StackOptr){
 m_StackOptr = a_StackOptr;
}

Stack * MathCalc::getStackOptr(){
 return m_StackOptr;
}

void MathCalc::setStackOpnd(Stack * a_StackOpnd){
 m_StackOpnd = a_StackOpnd;
}

Stack * MathCalc::getStackOpnd(){
 return m_StackOpnd;
}


double MathCalc::Calc(){

 Token token;
 int lastTokenType = Constant::BEGIN;

 if(m_strExpression[0] == 0){
  m_ErrCode = Constant::ERR_NO_EXPRESSION;
  return m_ErrCode;
 }

 m_StackOptr->InitStack();
 m_StackOpnd->InitStack();
 
 token.setType(Constant::BEGIN);
 m_StackOptr->Push(&token);

 strcat(m_strExpression, "#");

 m_strExpression = GetToken(&token);
 while(Constant::EMPTY!=token.getType()){
  if(Constant::ERROR == token.getType()){
   m_ErrCode = Constant::ERR_INVALID_CHAR;
   return m_ErrCode;
  }
  switch(token.getType()){
   case Constant::NUMBER:
    m_StackOpnd->Push(&token);
    lastTokenType=token.getType();
    break;
   case Constant::PLUS:
   case Constant::MINUS:
    if(lastTokenType!=Constant::NUMBER&&lastTokenType!=Constant::RPAREN){
     //判断如果结尾不是一个操作数或者不是一个右括号

     token.setType(Constant::SPECIAL);
     //将操作符的类型设置为SPECIAL(负号)

     lastTokenType=token.getType();
     //将操作符的类型置赋给lastTokenType;

     ProcessOpt(&token);
     //将Token的引用作为参数ProcessOpt;

     break;
    }
   case Constant::TIMERS:
   case Constant::DIVIDE:
   case Constant::POWER:
    if(lastTokenType!=Constant::NUMBER && lastTokenType!=Constant::RPAREN)
    {
     m_ErrCode=Constant::ERR_INVALID_OPT;
     return m_ErrCode;
    }
    lastTokenType=token.getType();
    ProcessOpt(& token);
    break;
   case Constant::LPAREN:
    if(lastTokenType==Constant::NUMBER)
    {
     m_ErrCode=Constant::ERR_LACK_OPT;
     return m_ErrCode;
    }
    lastTokenType=token.getType();
    ProcessOpt(& token);
    break;
   case Constant::RPAREN:
    if(lastTokenType!=Constant::NUMBER)
    {
     m_ErrCode=Constant::ERR_LACK_ARGUMENT;
     return m_ErrCode;
    }
    lastTokenType=token.getType();
    ProcessOpt(&token);
    break;
   case Constant::END:
    if(lastTokenType!=Constant::NUMBER && lastTokenType!=Constant::RPAREN)
    {
     m_ErrCode=Constant::ERR_LACK_ARGUMENT;
     return m_ErrCode;
    }
    lastTokenType = token.getType();
    ProcessOpt(&token);
    break;
  }
  m_strExpression = GetToken(&token);
 }

 if(!m_StackOptr->IsEmpty()){
  m_StackOptr->Pop(& token);
  m_ErrCode = Constant::ERR_LACK_ARGUMENT;
  return m_ErrCode;
 }

 if(m_StackOpnd->GetSize() > 1){
  m_ErrCode = Constant::ERR_LACK_OPT;
  return m_ErrCode;
 }
 m_ErrCode = Constant::ERR_NONE;
 m_StackOpnd->Pop(& token);
 return token.getOptrValue();
}

/*
*处理表达式元素压栈
*
*/
char * MathCalc::GetToken(Token * a_pToken){
 char * pchNextChar = NULL;
 int iLen = 0;

 if(NULL == m_strExpression || NULL == a_pToken){
  a_pToken->setType(Constant::EMPTY);
  return NULL;
 }

 pchNextChar = m_strExpression;

 while(' ' == * pchNextChar || '/t' == * pchNextChar){
  pchNextChar++;
 }

 if('/0' == * pchNextChar){
  a_pToken->setType(Constant::EMPTY);
  return pchNextChar;
 }

 switch(* pchNextChar){
  case '+':
   a_pToken->setType(Constant::PLUS);
   pchNextChar++;
   return pchNextChar;
  case '-':
 a_pToken->setType(Constant::MINUS);
   pchNextChar++;
   return pchNextChar;
  case '*':
   a_pToken->setType(Constant::TIMERS);
   pchNextChar++;
   return pchNextChar;
  case '/':
   a_pToken->setType(Constant::DIVIDE);
   pchNextChar++;
   return pchNextChar;
  case '^':
   a_pToken->setType(Constant::POWER);
   pchNextChar++;
   return pchNextChar;
  case '(':
   a_pToken->setType(Constant::LPAREN);
   pchNextChar++;
   return pchNextChar;
  case ')':
   a_pToken->setType(Constant::RPAREN);
   pchNextChar++;
   return pchNextChar;
  case '#':
   a_pToken->setType(Constant::END);
   return NULL;
  default:
   break;
 }

 if(isdigit(*pchNextChar)){
  iLen = 0;
  a_pToken->setType(Constant::NUMBER);
  while(isdigit(*pchNextChar)){
   a_pToken->setOpndID(*pchNextChar ,iLen);
   pchNextChar++;
   iLen++;
  }
  if('.' == * pchNextChar){
   a_pToken->setOpndID(* pchNextChar , iLen);
   pchNextChar++;
   iLen++;
   if(isdigit(*pchNextChar)){
    while(isdigit(* pchNextChar)){
     a_pToken->setOpndID(*pchNextChar , iLen);
     pchNextChar++;
     iLen++;
    }
   }
   else{
    a_pToken->setOpndID('/0' , iLen);
    a_pToken->setType(Constant::ERROR);
    return pchNextChar;
   }
  }
  a_pToken->setOpndID('/0' , iLen);
  a_pToken->setOptrValue(atof(a_pToken->getOpndID()));
  return pchNextChar;
 }

 a_pToken->setType(Constant::ERROR);
 a_pToken->setOpndID(* pchNextChar , 0);
 a_pToken->setOpndID('/0' , 1);
 return pchNextChar;
}

/*
*根据运算符优先级进行运算。
*/

int MathCalc::ProcessOpt(Token * a_pToken){
 Token topToken;
 char bFinished = 0;

 if(m_StackOptr->IsEmpty()){
  m_StackOptr->Push(a_pToken);
  return Constant::ERR_NONE;
 }
 while(!bFinished && !m_StackOptr->IsEmpty()){
  m_StackOptr->Top(&topToken);
  switch(aiPriority[topToken.getType()][a_pToken->getType()]){
  case 0:
   m_StackOptr->Pop(&topToken);
   a_pToken = NULL;
   bFinished = 1;
   break;
  case 1:
   DoCalc();
   break;
  case -1:
   bFinished = 1;
   break;
  default:
   m_ErrCode = Constant::ERR_INVALID_OPT;
   return m_ErrCode;
  }
 }
 if(a_pToken != NULL){
  m_StackOptr->Push(a_pToken);
 }
 return Constant::ERR_NONE;
}

/*
*执行单目运算
*参数说明:无
*返回值:错误代码
*
*/
int MathCalc::DoCalc(){
/*
*opt  操作符
*lNumber 左操作数
*rNumber 右操作数
*增加对负号的处理
*/
 Token opt , lNumber , rNumber;

 m_StackOptr->Pop(& opt);
 if(opt.getType()==Constant::SPECIAL){
  //如果作操数的类型为特殊符号

  m_StackOpnd->Pop(&lNumber);
  //弹出操作数

  lNumber.contrary();
  //对其进行取反运算

  m_StackOpnd->Push(&lNumber);
  //将操作数压入堆栈

  return Constant::ERR_NONE;
 }
 m_StackOpnd->Pop(& rNumber);
 m_StackOpnd->Pop(& lNumber);
 switch(opt.getType()){
 case Constant::MINUS:
  lNumber.setOptrValue(lNumber.getOptrValue()-rNumber.getOptrValue());
  break;
 case Constant::PLUS:
  lNumber.setOptrValue(lNumber.getOptrValue()+rNumber.getOptrValue());
  break;
 case Constant::TIMERS:
  lNumber.setOptrValue(lNumber.getOptrValue()*rNumber.getOptrValue());
  break;
 case Constant::DIVIDE:
  lNumber.setOptrValue(lNumber.getOptrValue()/rNumber.getOptrValue());
  break;
 case Constant::POWER:
  lNumber.setOptrValue(pow(lNumber.getOptrValue(),rNumber.getOptrValue()));
  break;
 default:
  return Constant::ERR_INVALID_OPT;
 }
 m_StackOpnd->Push(&lNumber);
 return Constant::ERR_NONE;
}

/*
*主方法
*/
void MathCalc::Main(){
 char buffer[129];
 do{
  cout<<"input Expression:/n";
  cin>>buffer;
  if(buffer[0] != 0){
   m_strExpression = buffer;
   m_Result = Calc();
   m_ErrCode = GetErrCode();
   if(m_ErrCode == Constant::ERR_NONE){
    cout<<"Expression Result:"<<m_Result<<endl;
   }
  else{   
   cout<<"Error:"<<GetErrMsg()<<endl;
   }
  }
 }while(buffer[0] != 0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值