您的位置:首页 > 编程语言

可以用于表达式处理的几个类的实现(源代码/无注释)

2004-08-13 08:31 441 查看
一直很想做个比Windows自带的高级一点的计算器,能将整个表达式输入,然后求值。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

这个程序要求读者具备编译原理的一些知识。

举个实例来说明程序处理过程。假设要求值的表达式为  -25*(56+15)#(其中#号作为表达式结束标志)。首先对表达式进行词法分析,允许出现的字符为{0 ,1, 2 ,3 ,4 ,5 ,6, 7 ,8, 9 . ,+ ,-, *, / ,( ,),#}分析的结果产生两种类型的单词:操作符和操作数。操作符包括:{+, - ,* ,/ ,( ,)}操作数包括int和double类型。上面表达式产生的单词序列为{-25,*,(,56,+,15,)}.这些单词的类型也需要保存。

           词法分析正确后将对产生的单词序列进行语法分析。

定义E为表达式,N为常数(视为终结符)。表达式的产生式可表示如下:

E à N   

E à (E)

E à E+E

E à E-E

E à E*E

E à E/E

 

消除左递归后的产生式(E_为新产生的符号):

E->NE_

E->(E)E_

E_->+EE_

E_->-EE_

E_->*EE_

E_->/EE_

E_->NULL  (空串)

 

可以根据这个产生式构造递归的语法分析器。具体细节就不叙述了,可以阅读源代码。

 

语法分析正确后就可以求值了,求值时用到一个操作数堆栈和操作符堆栈,以及一个算符优先表(存储了运算符之间的优先关系),具体细节可以阅读源码。
/*stack.h*/
template
class CStack 
{
public:
 CStack()
 {
  Head = new Node;
  Head->Next = NULL;
 }

 void Push(T data)
 {
  Node* tem;
  tem = Head->Next;
  Head->Next = new Node;
  Head->Next->Next = tem;
  Head->Next->Data = data;
 }
 

 BOOL Pop(T& data)
 {
  if(Head->Next)
  {
   data = Head->Next->Data;
   Node* tem = Head->Next->Next;
   delete Head->Next;
   Head->Next = tem;
   return TRUE;
  }
  else
   return FALSE;
 }

 BOOL GetTop(T& data)
 {
  if(Head->Next)
  {
   data = Head->Next->Data;
   return TRUE;
  }
  return FALSE;
 }

 virtual ~CStack()
 {
  Node* pNode = Head;
  Node* tem;
  while(pNode)
  {
   tem = pNode->Next;
   delete pNode;
   pNode = tem;
  }
 }

protected:
 struct Node
 {
  T Data;
  Node* Next;
 };

 Node* Head;

};

class PriorityTable
{

 int** pTable;
 int  TableSize;
public:
 PriorityTable()
 {
  int i,j;
  pTable =NULL;
  TableSize = 7;
  
  
  pTable = new int* [TableSize];
  for( i = 0; i < TableSize; i++)
   pTable[i] = new int[TableSize];
  
  for( i = 0; i < TableSize; i++)
   for( j = 0; j    pTable[i][j] = 1;

  pTable[4][5] = pTable[6][6] = 0;
  pTable[0][2] = pTable[0][3] = pTable[0][4] = -1;
  pTable[1][2] = pTable[1][3] = pTable[1][4] = -1;
  pTable[2][4] = -1;
  pTable[3][4] = -1;
  for( j = 0; j < 5; j++)
   pTable[4][j] = -1;
  for( j = 0; j < 5; j++)
   pTable[6][j] = -1;
 
 }

 

 ~PriorityTable()
 {
  
  for(int i=0; i< TableSize ; i++)
  {
   delete []pTable[i];
  }
   delete []pTable;
  
 }

 int CharToIndex(char ch)
 {
  switch (ch)
  {
  case '+':
      return 0;
  case '-':
      return 1;
  case '*':
      return 2;
  case '/':
      return 3;
  case '(':
      return 4;
  case ')':
      return 5;
  case '#':
      return 6;
  default:
      return -1;
  }
 }

 int Compare(const char FirstOper,const char SecondOper)
 {
  int FirstIndex  = CharToIndex(FirstOper);
  int SecondIndex = CharToIndex(SecondOper);
  if(FirstIndex != -1 && SecondIndex != -1 )
   return pTable[FirstIndex][SecondIndex];
  return -2;
 }

 int Compare(int x,int y)
 {
  if( x>=0 && x=0 && y   return pTable[x][y];
  return -2;
 }

};

// ForTest.cpp : Defines the entry point for the console application.
//

 

#define MaxWordNum 100
#define MaxWordLength 100

class WordAnalyse
{
protected:
 
 char Words[MaxWordNum][MaxWordLength];
 int  WordsAttribute[MaxWordNum];
 int CurrentWordNum;
 char* pCurrentLocation ;
 char* pLastLocation;
 bool bResult;
 bool WordType; 
 char Expression[100];
public:
 
 WordAnalyse(char* chExpression)
 {
  
  int i,j;
  for(i = 0; i   
  {
   for(j = 0; j    Words[i][j] = '/0';
   WordsAttribute[i] = 0;
   
  }
  CurrentWordNum = 0;
  pCurrentLocation = NULL;
  strcpy(Expression,"(");
  strcat(Expression,chExpression);
  pCurrentLocation = Expression+1;
  pLastLocation = Expression;
  bResult = WordsAnalyse();
  WordType = IsAllDouble();
 }

 int GetWordNum()
 {
  return CurrentWordNum;
 }
 
 char* GetWord(int index)
 {
  if(index>=CurrentWordNum)
   return NULL;
  else
   return Words[index];
 }

 int GetWordAttribute(int index)
 {
  if(index>=CurrentWordNum)
   return -100;
  return WordsAttribute[index];
 }

 bool GetResult()
 {
  return  bResult ;
 }

 bool TypeIsDouble()
 {
  return WordType;
 }

 

 

protected:

 bool IsAllDouble()
 {
  for(int i = 0;i  {
   if(WordsAttribute[i] == 1 || !strcmp(Words[i],"/"))
    return true;
  }
  return false;
 }

 bool WordsAnalyse()
 {
  
  while(*pCurrentLocation != '/0')
   if(!GenerateWord())
    return false;
   return true;
   
 }

 bool IsNumber(char ch)
 {
  if(ch >= '0' && ch <= '9')
   return true;
  return false;
 }

 bool GenerateWord()
 {
  
  if(*pCurrentLocation == ' ')
   do
   {
    pCurrentLocation++;
   }
   while(*pCurrentLocation == ' ');
   
   switch(*pCurrentLocation)
   {
   case '+':
   case '*': 
   case '/': 
   case '(':
   case ')': 
   case '#':
    Words[CurrentWordNum][0] = *pCurrentLocation;
    WordsAttribute[CurrentWordNum] = 2;
    CurrentWordNum++;
    pLastLocation = pCurrentLocation;
    pCurrentLocation++;
    
    return true;
   case '-':    
    if(*pLastLocation != '(')    // - 号为双目操作符
    {
     Words[CurrentWordNum][0] =

*pCurrentLocation;
     WordsAttribute[CurrentWordNum] = 2;
     
    }
    else                             //-为单目操作符
    {
     Words[CurrentWordNum][0] = '0';
     WordsAttribute[CurrentWordNum] = 0;
     CurrentWordNum++;

     Words[CurrentWordNum][0] = '-';
     WordsAttribute[CurrentWordNum] = 2;
    
    }

    CurrentWordNum++;
    pLastLocation = pCurrentLocation;
    pCurrentLocation++;
    
    return true;
   
   case '0':
   case '1':
   case '2':
   case '3':
   case '4':
   case '5':
   case '6':
   case '7':
   case '8':
   case '9':
    int i ;
    i = 0;
    do
    {
     Words[CurrentWordNum][i++] =

*pCurrentLocation;
     pLastLocation = pCurrentLocation;
     pCurrentLocation++;
    }while(IsNumber(*pCurrentLocation));
    
    if(*pCurrentLocation == '.')
    {
     
     Words[CurrentWordNum][i++] =

*pCurrentLocation;
     pCurrentLocation++;
     if(!IsNumber(*pCurrentLocation))
      return false;
     while(IsNumber(*pCurrentLocation))
     {
      Words[CurrentWordNum][i++] =

*pCurrentLocation;
      pLastLocation = pCurrentLocation;
      pCurrentLocation++;
     }
     WordsAttribute[CurrentWordNum] = 1;
     CurrentWordNum ++;
     return true;
    }
    else
    {
     CurrentWordNum ++;
     return true;
    }
    
   default :
    return false;
    
   }
 
   return false;
 }
 

};

 

#include "WordAnalyse.h"

 

class SyntaxAnalyse
{
 bool bResult;
 int WordIndex;
public:
 SyntaxAnalyse() {bResult = true;  WordIndex = 0;}
 bool Analyse(WordAnalyse* pWords);
protected:
 void E(WordAnalyse* pWords);
 void E_(WordAnalyse* pWords);
// void N(WordAnalyse* pWords);
};

bool SyntaxAnalyse::Analyse(WordAnalyse* pWords)
{
 if(pWords->GetResult() == false)
  return false;
 E(pWords);
 if( WordIndex < pWords->GetWordNum() - 1)
 {
   bResult = true;
   WordIndex = 0;
   return false;
 }
 bool tem = bResult;
 bResult = true;
 WordIndex = 0;
 return tem;

}

void SyntaxAnalyse::E(WordAnalyse* pWords)
{
 
 if(strcmp(pWords->GetWord(WordIndex),"(") == 0)
 {
  WordIndex++;
  E(pWords);
  if(strcmp(pWords->GetWord(WordIndex),")") == 0)
  {
   WordIndex++;
   E_(pWords);
  }
  else
  {
   bResult = false;
   return;
  }
  
 }
 else
  if(pWords->GetWordAttribute(WordIndex) != 2)
  {
   WordIndex++;
   E_(pWords);
  }
  else
  {
   bResult = false;
   return;
  }
}

void SyntaxAnalyse::E_(WordAnalyse* pWords)
{
 //char tem[100] = "/0";
// strcpy(tem,Words.GetWord(WordIndex));
// char Operator = tem[0];
 if(strcmp(pWords->GetWord(WordIndex),"+") == 0 ||
  strcmp(pWords->GetWord(WordIndex),"-") == 0 ||
  strcmp(pWords->GetWord(WordIndex),"*") == 0 ||
  strcmp(pWords->GetWord(WordIndex),"/") == 0
  )
 {
  WordIndex++;
  E(pWords);
  E_(pWords);
 }
 else
  return;
 
}
#include "stack.h"
#include "CompareTable.h"
#include "SyntaxAnalyse.h"

 

class  CalExpression
{
public:
 CalExpression(char* Expression);
 int GetValueType();
 int GetIntResult();
 double GetDoubleResult();
 bool GetResult();
 int Calculate();
protected:
 int Operate(char Operator,int Fir,int Sec);
 double Operate(char Operator,double Fir,double Sec);
protected:

 PriorityTable  MyTable;
 WordAnalyse MyWords;
 SyntaxAnalyse MySyntax;
protected:
 bool bResult;
 int nResult;
 double dResult;
 int ValueType;
};

CalExpression::CalExpression(char* Expression):MyWords(Expression)
{
 bResult = false;
 nResult = 0;
 dResult = 0;
 ValueType = -1;
}

bool CalExpression::GetResult()
{
 return bResult;
}

int CalExpression::GetValueType()
{
 return ValueType;
}

int CalExpression::Operate(char Operator,int Fir,int Sec)
{
 switch (Operator)
 {
 case '+':
  return Fir+Sec;
 case '-':
  return Fir - Sec;
 case '*':
  return Fir * Sec;
 case '/':
  return Fir/Sec;
 }
 return 0;
}

double CalExpression::Operate(char Operator,double Fir,double Sec)
{
 switch (Operator)
 {
 case '+':
  return Fir+Sec;
 case '-':
  return Fir - Sec;
 case '*':
  return Fir * Sec;
 case '/':
  return Fir/Sec;
 }
 return 0;
}

int CalExpression::GetIntResult()
{
 return nResult;
}

double CalExpression::GetDoubleResult()
{
 return dResult;
}

int CalExpression::Calculate()
{
 bResult = false;
 nResult = 0;
 dResult = 0;
 ValueType = -1;

 if(!MySyntax.Analyse(&MyWords))
  return ValueType = -1;
 if(MyWords.TypeIsDouble())
 {
  CStack CharStack;
  CStack  ValueStack;

  CharStack.Push('#');
  
  int WordIndex = 0;
  
  char top;
  CharStack.GetTop(top);
  while(!(strcmp(MyWords.GetWord(WordIndex),"#") == 0 && top ==

'#'))
  {
   if(MyWords.GetWordAttribute(WordIndex) != 2)
   {
    double Value = atof(MyWords.GetWord(WordIndex));
    ValueStack.Push(Value);
    WordIndex ++;
    
   }
   else
   {
    switch (MyTable.Compare(top,(MyWords.GetWord

(WordIndex))[0]))
    {
    case -1:
     CharStack.Push((MyWords.GetWord

(WordIndex))[0]);
     WordIndex ++;
     break;
    case 0:
     CharStack.Pop(top);
     WordIndex ++;
     break;
    case 1:
     {
      double nFirNum ,nSecNum, nResult;
      char Operator;
      ValueStack.Pop(nSecNum);
      ValueStack.Pop(nFirNum);
      CharStack.Pop(Operator);
      nResult = Operate

(Operator,nFirNum,nSecNum);
      ValueStack.Push(nResult);
      break;
     }
    default :
     break;
    }
   }
   
   
   CharStack.GetTop(top);
  }

  ValueStack.GetTop(dResult );
  ValueType = 1;
  return 1;
 }
 else
 {
  CStack CharStack;
  CStack  ValueStack;
  
  CharStack.Push('#');
  
  int WordIndex = 0;
  
  char top;
  CharStack.GetTop(top);
  while(!(strcmp(MyWords.GetWord(WordIndex),"#") == 0 && top ==

'#'))
  {
   if(MyWords.GetWordAttribute(WordIndex) != 2)
   {
    int Value = atoi(MyWords.GetWord(WordIndex));
    ValueStack.Push(Value);
    WordIndex ++;
    
   }
   else
   {
    switch (MyTable.Compare(top,(MyWords.GetWord

(WordIndex))[0]))
    {
    case -1:
     CharStack.Push((MyWords.GetWord

(WordIndex))[0]);
     WordIndex ++;
     break;
    case 0:
     CharStack.Pop(top);
     WordIndex ++;
     break;
    case 1:
     {
      int nFirNum ,nSecNum,nResult;
      char Operator;
      ValueStack.Pop(nSecNum);
      ValueStack.Pop(nFirNum);
      CharStack.Pop(Operator);
      nResult = Operate

(Operator,nFirNum,nSecNum);
      ValueStack.Push(nResult);
      break;
     }
    default :
     break;
    }
   }
   
   
   CharStack.GetTop(top);
  }

  ValueStack.GetTop(nResult );
  ValueType = 0;
  return 0;

 }
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐