將一般表達式轉換爲後綴式,並利用後綴式計算結果

       最近回頭看下之前寫的代碼,有點感觸,忽然覺得應該把這些練習保存下來,算是對年少努力歷程的見證吧。畢竟是大一大二時寫的,其中的代碼難免有較多水貨,不過也懶得改了,就讓它真實着過去吧。

  

 

下面是"將一般表達式轉換爲後綴式,並利用後綴式計算結果"的簡單程序代碼實現:

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

主函數部分

#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;}
}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章