最近回頭看下之前寫的代碼,有點感觸,忽然覺得應該把這些練習保存下來,算是對年少努力歷程的見證吧。畢竟是大一大二時寫的,其中的代碼難免有較多水貨,不過也懶得改了,就讓它真實着過去吧。
下面是"將一般表達式轉換爲後綴式,並利用後綴式計算結果"的簡單程序代碼實現:
---------------------------------------------------------------------------------------------------------------------------
主函數部分
#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;}
}