将一般表达式转换为后缀式,并利用后缀式计算结果

       最近回头看下之前写的代码,有点感触,忽然觉得应该把这些练习保存下来,算是对年少努力历程的见证吧。毕竟是大一大二时写的,其中的代码难免有较多水货,不过也懒得改了,就让它真实着过去吧。

  

 

下面是"将一般表达式转换为后缀式,并利用后缀式计算结果"的简单程序代码实现:

---------------------------------------------------------------------------------------------------------------------------

主函数部分

#include "stdafx.h"

#include "evaluation.h"
#include "MatchPairs.h"

int _tmain(int argc, _TCHAR* argv[])
{  
 Expression a(6);

 std::cout<<"请输入长度为"<<a.Size()<<"的表达式\n";
 std::cin>>a;//输入表达式

 //若输入的表达式括号匹配成功则开始转换
 if(MatchedPairs(a.Expr())){
  a.Transform();//转换成后缀式
  a.OutputTexpr();//输出后缀表达式
  std::cout<<"\n表达式计算结果为:"<<a.Evaluation()<<"\n";
 }

 return 0;
}

 

 

-------------------------------------------------------------------------------------------------------------------------

//evaluation.h

/*
  版本:vs2010
  作者:xiluoduyu
  时间(年-月-日):2011.09.28
  功能描述:将一般表达式转换为后缀式,并利用后缀式计算结果
  修改时间:
  修改内容:
*/

#pragma once

#include"stdafx.h"
#include"LinkedStack.cpp"

 

//表达式类声明

 

class Expression
{
  public:

   Expression(int a=0){
   size=a;expr=new char[a+1];Transedexpr=new char[a+1];}

   Expression(char a[]);//初始化表达式

   ~Expression(){delete []expr; delete[]Transedexpr;}

   void Transform();//把表达式转换为后缀式
  
   void OutputTexpr();//输出后缀表达式

   double Evaluation();//计算后缀式表达式的结果

   void InputExpr(std::istream& in);//输入表达式

   char* Expr()const{return expr;}
   int Size()const{return size;}

  private:

 char* TransformInkuohao(char* begin,char temp[]);//在括号内从“(”至“)”的运算

 bool Notbigger(const char& stackopr,const char& expropr);//运算符的比较函数
  private:
  int size;
  char* expr;//存储输入的表达式数组
  char* Transedexpr;//存储后缀式数组
  LinkedStack<double> NumberStack;//操作数栈
  LinkedStack<char> OperatorStack;//操作符栈
};

 

 

//表达式类定义

 

//构造函数
Expression::Expression(char a[])
{//"#"为表达式结束符
  int temp=sizeof(a+1),i=0;

  expr=new char[temp];

  for(;i<temp;i++)
   expr[i]=a[i];

  expr[i]='#';
}

//后缀式输出函数
void Expression::OutputTexpr()
{
 int i=0;
 std::cout<<"后缀表达式为:\n";

 while(Transedexpr[i]!='#') {

      if(Transedexpr[i]=='.')
   std::cout<<'.';

   else if(Transedexpr[i]=='|')
   std::cout<<" ";

   else std::cout<<Transedexpr[i];
   i++;  }

   std::cout<<std::endl;
}

//输入函数
void Expression::InputExpr(std::istream& in)

 
    char *temp=new char[size];
 for(int i=0;i<size;i++)
  in>>temp[i];
 
 int j=0;//expr的索引
 for(int i=1;i<=size;i++,j++)
  if(temp[i-1]=='(' && temp[i]=='-')//若遇到负数则在负数前面加0
    {expr[j++]=temp[i-1]; expr[j]='0';}
  else {expr[j]=temp[i-1];}
 expr[j]='#';//尾结束符
}
//重载>>
std::istream& operator >>(std::istream& in,Expression& x)
{
 x.InputExpr(in);
 return in;
}

//计算后缀式表达式的结果
double Expression::Evaluation()
{
 double b=0,c=0;//存放NumberStack的栈顶元素

 double result=0;//存放结果

 int i=0;//Transedexpr的索引

 while(Transedexpr[i]!='#')
 {
   if(Transedexpr[i]>='0' && Transedexpr[i]<='9') {//Transedexpr[i]为操作数数

   char *c=new char[20];//存储数字的数组
   int n=0;//数组索引

        while(Transedexpr[i]!='|')
   c[n++]=Transedexpr[i++];

    //将字符型Transedexpr[i]转换为int型
   // int k=(int)Transedexpr[i]-48;
   double k=atof(c);

   NumberStack.Add(k); //将操作数压栈

      delete []c;}
     
   else {//弹出栈顶的两个元素

      NumberStack.Delete(b);//b为后操作数

      NumberStack.Delete(c);//c为前操作数

     //运算
     switch(Transedexpr[i]) {
   
      case '+':NumberStack.Add(c+b);
       break;

      case '-':NumberStack.Add(c-b);
       break;

      case '*':NumberStack.Add(c*b);
       break;

      case '/':NumberStack.Add(c/b);
       break;

      default:std::cerr<<"操作符有误!\n";
       break;

      }

     }

   i++;

 }

 NumberStack.Delete(result);//从栈中提取结果

 return result;
}

//转换函数Transform
void Expression::Transform()
{//将expr转换为Transexpr
   //即将表达式转换为相应的后缀表达式

 int j=0;//Transedexpr的索引

 char* current=expr;//expr的索引
 
 while(*(current)!='#')
 {

 //若读到一个操作数,就把它作为后缀表达式的一部分放进Transedexpr
  if(*(current)>='0' && *(current)<='9') {

          while(*(current)>='0' && *(current)<='9' || *(current)=='.') {
      Transedexpr[j]=*(current);
      j++;
      current++;  }

    Transedexpr[j++]='|';//两个数据之间以“|”分隔

  }//expr的索引前移


        else if(*(current)!='('){ //每当读到一个运算符时,就将其优先级与栈顶位置运算符优先级
       // 进行比较,以决定是把读到的运算符进栈,还是将栈顶位置的
        //运算符作为后缀表达式的一部分输出

    while(!OperatorStack.IsEmpty() && //栈非空
      Notbigger(OperatorStack.Top(),*(current)) ) {//运算符优先级低于或等于栈顶位置运算符优先级

         OperatorStack.Delete( Transedexpr[ j ] );//运算符出栈

      j ++;  }
      
      //运算符优先级高于或等于栈顶位置运算符优先级
    OperatorStack.Add(*(current));//运算后将当前运算符压栈
    current++;
      }
  

     //若读到括号开始符则先完成括号内部运算
  else
  { 
   char* temp=new char[20];

   //调用括号内转换函数,并返回转换结果temp,temp以“#”为结束符
   current=TransformInkuohao(&*(++current),temp);//函数返回的current的当前状态为“)”
   current++;
         //将括号内的转换结果赋给Transedexpr,同时expr的索引前移
   for(int k=0;temp[k]!='#';k++) {

   Transedexpr[j]=temp[k];

   j++; }

  //释放temp的空间
   delete []temp;

   }

  }

 //余下的运算符全部作为后缀表达式的一部分输出
 while(!OperatorStack.IsEmpty())

  OperatorStack.Delete(Transedexpr[j++]);

    Transedexpr[j]='#';//后缀表达式结束符号
}

 

//括号内转换函数TransformInkuohao
 char* Expression::TransformInkuohao(char* begin,char temp[])
{//将括号内部表达式转换为相应的后缀表达式
  //begin的当前状态为“(”的下一符号,temp用于记录内部后缀表达式

//声明要用到的变量
 LinkedStack<char> OperatorStack;//内部操作符栈

 char* Incurrent=begin;//括号内expr的遍历指针

 int j=0;//temp的索引


括号内运算关键模块
 
 while(*(Incurrent)!=')')
 {
  //若读到一个操作数,就把它作为后缀表达式的一部分放进tempTrdexpr
  if(*(Incurrent)>='0' && *(Incurrent)<='9') {

    while(*(Incurrent)>='0' && *(Incurrent)<='9' || *(Incurrent)=='.')
     {
   temp[ j ] = *(Incurrent);
   j ++;
      Incurrent++;  }

      temp[j++]='|';

      Incurrent--;
    }

  else if(*(Incurrent)=='(')  {//若括号内镶嵌括号

   char* Intemp= new char[20];

   Incurrent=TransformInkuohao(++Incurrent,Intemp);
   Incurrent++;

   for(int i=0;Intemp[i]!='#';i++) {
    temp[j]=Intemp[i];
    j++;  }

   delete []Intemp;

   continue;//已完成括号内镶嵌的括号转换,继续下一轮循环
   }


  else { //每当读到一个运算符时,就将其优先级与栈顶位置运算符优先级
       // 进行比较,以决定是把读到的运算符进栈,还是将栈顶位置的
        //运算符作为后缀表达式的一部分输出

    while(!OperatorStack.IsEmpty() && //栈非空
      Notbigger(OperatorStack.Top(),*(Incurrent)) ) {//运算符优先级低于或等于栈顶位置运算符优先级

         OperatorStack.Delete( temp[ j ] );//运算符出栈

      j ++;  }
      
      //运算符优先级高于或等于栈顶位置运算符优先级
    OperatorStack.Add(*(Incurrent));//运算后将当前运算符压栈

      }

  Incurrent++;//当前指针前移

  }


余下的运算符全部作为后缀表达式的一部分输出
 while(!OperatorStack.IsEmpty())

  OperatorStack.Delete( temp[ j++ ] );

    temp[ j ]='#';//后缀表达式结束符号


返回结束位置
    return Incurrent;
}


bool Expression::Notbigger(const char& stackopr,const char& expropr)
{//stackopr为栈顶运算符,expropr为表达式运算符

   switch(expropr){

    case '+':  if( stackopr=='+' ||stackopr=='-' ||stackopr=='*' || stackopr=='/')return true;else return false;

    case '-':  if( stackopr=='+' ||stackopr=='-' ||stackopr=='*' || stackopr=='/')return true;else return false; 

    case '/':  if(stackopr=='*' || stackopr=='/')return true;else return false;

    case '*':  if(stackopr=='*' || stackopr=='/')return true;else return false;

    default: std::cerr<<"函数Notbigger外部限制条件不足!\n";return false;

      }
 }

 

-------------------------------------------------------------------------------------------------------------------------------------

判断输入的表达式中的括号是否匹配函数定义

//MatchPairs.h

#pragma once
#include"stdafx.h"
#include"LinkedStack.cpp"
#include<string>


bool MatchedPairs(char* expr)
{//括号匹配
 LinkedStack<int> s;
 int j,length=1;

 for(int i=0;expr[i]!='#';i++,length++);//计算expr的字符个数

 //从表达式expr中搜索(和)
 for(int i=1;i<=length;++i){
  //遇到非法符号则结束
  if(  expr[i-1]!='(' && expr[i-1]!=')'&&//若不是正确的括号
   ( expr[i-1]<'0'|| expr[i-1]>'9')&& //也不是数字
   expr[i-1]!='.' && expr[i-1]!='#' &&//也不是小数点
   ( expr[i-1]!='+' && expr[i-1]!='-' && expr[i-1]!='*' && expr[i-1]!='/')//不是运算符
    ) {
   std::cerr<<"表达式中第"<<i<<"个位置出现非法符号!\n";
   return false; }//结束

  if(expr[i-1]=='(') s.Add(i);

  else if(expr[i-1]==')')
       try{ s.Delete(j);}

       catch(OutOfBounds()) {
         std::cerr<<"No match for right parenthesis at"<<i<<std::endl;
         return false; }
 }
 //堆栈中所剩下的(都是未匹配的
 while(!s.IsEmpty()){
  s.Delete(j);
  std::cout<<"No match for left parenthesis at"<<j<<std::endl;
     return false;}
 return true;
}

 

------------------------------------------------------------------------------------------------------------------------

用于存储表达式的模板类栈的声明

//LinkedStack.h

#pragma once


template<class T>class LinkedStack;
template<class T>
class Node{
 friend LinkedStack<T>;
private:
 T data;
 Node<T>* link;
};

template<class T>
class LinkedStack
{
public:
 LinkedStack(){top=0;}
 ~LinkedStack();
 bool IsEmpty()const {return top==0;}
 bool IsFull()const;
 T Top()const;
 LinkedStack<T>& Add(const T& x);
 LinkedStack<T>& Delete(T& x);
 void OutputStack();
private:
 Node<T>* top;//指向栈顶结点
};

class OutOfBounds
{
public:
 OutOfBounds(){std::cerr<<"OutOfBounds!"<<std::endl;}
};

 

----------------------------------------------------------------------------------------------------------------------------------------

模板类定义

//LinkedStack.cpp


#pragma once

#include"stdafx.h"
#include"LinkedStack.h"

 


template<class T>
LinkedStack<T>::~LinkedStack()
{//析构函数
 Node<T>* next;
 while(top){
  next=top->link;
  delete top;
     top=next;
 }
}

template<class T>
bool LinkedStack<T>::IsFull()const
{
 try{Node<T>* p=new Node<T>;
          delete p;
   return false;
 }
 catch(std::bad_alloc& ){return true;}
}

template<class T>
T LinkedStack<T>::Top()const
{
if(IsEmpty())throw OutOfBounds();
return top->data;
}

template<class T>
LinkedStack<T>& LinkedStack<T>::Add(const T& x)
{
 Node<T>* p=new Node<T>;
 p->data=x;
 p->link=top;
 top=p;
 return *this;
}

template<class T>
LinkedStack<T>& LinkedStack<T>::Delete(T& x)
{//删除栈顶元素,并将其送入x
    if(IsEmpty())throw OutOfBounds();
 x=top->data;
 Node<T>* p=top;
 top=top->link;
 delete p;
 return *this;
}

//输出栈元素
template<class T>
void LinkedStack<T>::OutputStack()
{
 if(!IsEmpty())
 {
   Node<T>* current;
   while(top)
   {
    std::cout<<top->data<<' ';
    current=top;
    top=top->link;
    delete current;
       }
 }
 else {std::cerr<<"The stack is empty!"<<std::endl;}
}

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值