用c++实现中序表达式求值

本文介绍了一种使用栈实现表达式求值的算法,详细解释了如何处理各种运算符及括号,包括负数的特殊处理方式。通过两个栈分别存储运算符和操作数,实现了表达式的高效解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

表达式中所涉及的运算符有:单目运算符+-,双目运算符+, -, *, /, %,^(a^b=pow(a,b))

表达式中,负数必须写成形式为:(-num),其中num>0,表达式必须以等号结束

基本思想:

利用两个栈,一个为运算符栈operatorstack,一个为运算数栈operandstack,得到输入表达式后,从左到右扫描式子,若为运算数,压入operandstack,运算符则先与栈operatorstack栈顶元素进行优先级比较,若小于栈顶元素,则弹出该栈顶元素,并从栈operandstack中弹出两个操作数进行计算,结果压入operandstack。

为了处理形式为(-num),设置两个标志int preisopr(前一元素为操作符)int preisopd(前一元素为操作数),如果 preisopr==2则将num 取反压入operandstack

代码如下:(其中lstack.h为链栈,代码在本blog中的栈与链栈中,地址:http://blog.csdn.net/iamsnowolf/archive/2007/03/02/1519714.aspx

//3.2.07
//expression.cpp
//------------------------------------------------
#include<iostream.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h> //用于函数isdigit
#include"lstack.h"
//---------------------------------------------------
// 运算符   读入优先级  栈优先级  等级
// (单目)+-          0
// +-    1    1    -1
// */%    2    2    -1

// ^    3    3    -1

// (    4    -1    0
// )    0    0    0
//
//
//--------------------------------------------------
class MathOperator
{
private:
 //运算符及其优先级
 char opr;
 int inputprecedence;
 int stackprecedence;
public:
 MathOperator(void){};
 MathOperator(char ch);

 int operator>=(MathOperator a) const;
 void Evaluate(lstack<float> &operandstack);
 char GetOpr(void) const;
};
MathOperator::MathOperator(char ch)
{
 opr=ch;
 switch(ch)
 {
 case '^': inputprecedence=3;
    stackprecedence=3;
    break;
 case '+':
 case '-': inputprecedence=1;
    stackprecedence=1;
    break;
 case '*':
 case '/':
 case '%': inputprecedence=2;
    stackprecedence=2;
    break;
 case '(': inputprecedence=3;
    stackprecedence=-1;
    break;
 case ')': inputprecedence=0;
    stackprecedence=0;
    break;
 }
}
int MathOperator::operator >=(MathOperator a) const
{
 return stackprecedence>=a.inputprecedence;
}
void MathOperator::Evaluate(lstack<float> &operandstack)
{
 float operand1=operandstack.Pop();
 float operand2=operandstack.Pop();
 switch(opr)
 {
 case '+': operandstack.Push(operand2+operand1);
    break;
 case '-': operandstack.Push(operand2-operand1);
    break;
 case '*': operandstack.Push(operand2*operand1);
    break;
 case '/': operandstack.Push(operand2/operand1);
    break;
 case '%': operandstack.Push((int)operand2%(int)operand1);
    break;
 case '^': operandstack.Push(pow(operand2,operand1));
    break;
 }
}
char MathOperator::GetOpr(void) const
{
 return opr;
}

//检查读入字符是否为运算符或左括号,是返回1,不是返回0
const int MAXOPTR=7;
char optr[MAXOPTR]={'+','-','*','/','(','%','^'};
int isoperator(char ch)
{
 int i=0,flag=1;
 char c;
 while(flag&&i<MAXOPTR)
 {
  if(ch==(c=optr[i]))
   flag=0;
  else i++;
 }
 return !flag;
}
int iswhitespace(char ch)
{
 if(ch==' '||ch=='/n'||ch=='/t')
  return 1;
 else return 0;
}

//出错处理
enum ErrorType{Operator,Operand,Left,Right,Invalid};
void Error(int n)
{
 static char *errormsgs[]={
   "Operator expected",
   "Operand expected",
   "Missing left parenthesis",
   "Missing right parentheses",
   "Invalid input"
 };
 cerr<<errormsgs[n]<<endl;
 exit(1);
};

//表达式求值
float evaluate(void)
{
 lstack<float> operandstack;
 lstack<MathOperator> operatorstack;
 MathOperator opr1,opr2;
 int rank=0;
 int preisopr=0; //前一数据是操作符
 int preisopd=0; //前一数据是操作数
 float number;
 char ch;
 //处理表达式直到读入=
 while(cin.get(ch)&&ch!='=')
 {
  //-----处理浮点数
  if(isdigit(ch)||ch=='.')
  {
   cin.putback(ch);
   cin>>number;
   rank++; //操作数级别为1
   if(rank>1)
    Error(Operator);
   if(preisopr==2) //如果是负数
    number=-number;
   operandstack.Push(number);
   preisopr=0;
   preisopd=1;
  }
  //-----处理运算符
  else if(isoperator(ch))
  {
   
   if(ch!='(')
   {
    if(preisopr==0&&preisopd==1) //如果是双目运算符
    {
     preisopr++;
     preisopd=0;
     rank--; //操作符级别为-1
    }
    else if(preisopr==0&&preisopd==0) //如果是单目运算符
    {
     if(ch!='-')Error(Invalid);
     preisopr=2;
     continue;
    }
    else if(preisopr==1) //如果是单目运算符
    {
     
     if(ch!='-')Error(Invalid);preisopr++;
     continue;
    }
    else if(preisopr>=2) //非法
     Error(Invalid);
   }
   if(rank<0)
    Error(Operand);
   //建立一个存放当前运算符的MathOperator对象,其栈顶运算符的优先级>=
   //当前运算符优先级,则弹出栈顶运算符并执行其运算。将当前运算符压入栈中
   opr1=MathOperator(ch);
   while(!operatorstack.StackEmpty()&&(opr2=operatorstack.Peek())>=opr1)
   {
    opr2=operatorstack.Pop();
    opr2.Evaluate(operandstack);
   }
   operatorstack.Push(opr1);
  }
  //-----处理右括号
  else if(ch==')')
  {
   //建立一个存放)的MathOperator对象,弹出运算符栈并求值直到遇到(或栈为空
   //若栈为空则遗失(,否则删除(
   opr1=MathOperator(ch);
   while(!operatorstack.StackEmpty()&&(opr2=operatorstack.Peek())>=opr1)
   {
    opr2=operatorstack.Pop();
    opr2.Evaluate(operandstack);
   }
   if(operatorstack.StackEmpty())
    Error(Left);
   opr2=operatorstack.Pop(); //删除(
  }
  //---非法输入
  else if(!iswhitespace(ch))
  { Error(Invalid);}
 }
 //完整表达式的级别应为1
 if(rank!=1)
  Error(Operand);
 //用运算符栈完成表达式求值,若发现坐括号,则遗失右括号
 while(!operatorstack.StackEmpty())
 {
  opr1=operatorstack.Pop();
  if(opr1.GetOpr()==')')
   Error(Left);
  opr1.Evaluate(operandstack);
 }
 return operandstack.Pop();
}
int main(void)
{
 float num;
 num=evaluate();
 cout<<num<<endl;
 return(0);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值