最近回头看下之前写的代码,有点感触,忽然觉得应该把这些练习保存下来,算是对年少努力历程的见证吧。毕竟是大一大二时写的,其中的代码难免有较多水货,不过也懒得改了,就让它真实着过去吧。
下面是"将一般表达式转换为后缀式,并利用后缀式计算结果"的简单程序代码实现:
---------------------------------------------------------------------------------------------------------------------------
主函数部分
#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;}
}