关于后缀表达式的计算机求值以及中缀表达式转后缀表达式的分析请看我的另一篇博客——中缀表达式转前、后缀表达式及其求值
后缀表达式求值
#include<iostream>
#include<iomanip>
#include<cstdlib>
#include<cctype>
#include<cmath>
using namespace std;
#define MaxSize 100 //堆栈元素的最大个数
#define MaxOP 100 //运算数序列可能的最大长度
#define Number 0 //运算数的标识
#define ZERO 1.0E-10 //ZERO无限接近于0
typedef double ElementType; //将堆栈元素类型具体化
typedef struct SNode *Stack;
struct SNode{
ElementType data[MaxSize];
int top;
};
//建立空栈
Stack CreateStack()
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->top = -1;
return S;
}
//入栈
void Push(Stack PtrS,ElementType X)
{
if(PtrS->top==MaxSize-1)
cout<<"堆栈满"<<endl;
else
PtrS->data[++(PtrS->top)]=X;
}
//出栈
#define Error -1
ElementType Pop(Stack PtrS)
{
if(PtrS->top==-1){
cout<<"空栈"<<endl;
return Error;
}else{
return (PtrS->data[(PtrS->top)--]);
}
}
int GetOp(char s[])
{
/*从输入中获得下一个对象(运算符或运算数),并保存在字符数组s里*/
/*返回值为Number或者运算符本身*/
int i,c;
/*跳过表达式前空格等字符*/
while((s[0] = c = getchar()) == ' '||c == '\t');
s[1] = '\0';
if(!isdigit(c)&&c!='.') //如果c是运算符
return c; //直接返回运算符
i = 0;
if(isdigit(c)) //如果c是数字,则一直读完连续的数字并存入s
while(isdigit(s[++i] = c = getchar()));
if(c == '.') //如果有小数点,则一直读完小数点后的连续数字
while(isdigit(s[++i] = getchar()));
s[i] = '\0'; //完成对实数字符串的存储
return Number;
}
//例子
int main()
{
int Type;
ElementType pre;
char s[MaxOP];
Stack Ptr = CreateStack();
while((Type = GetOp(s)) != EOF){ //当未读到输入结束时
switch(Type){
case Number:Push(Ptr,atof(s));
break;
case'+':Push(Ptr,Pop(Ptr)+Pop(Ptr));
break;
case'*':Push(Ptr,Pop(Ptr)*Pop(Ptr));
break;
case'-':pre = Pop(Ptr);
Push(Ptr,Pop(Ptr)-pre);
break;
case'/':pre = Pop(Ptr);
if(fabs(pre) > ZERO) //检查除法的分母是否为0
Push(Ptr,Pop(Ptr)/pre);
else
cout<<"error:zero divisor"<<endl;
break;
case'\n':cout<<setprecision(8)<<Pop(Ptr)<<endl; //小数点后最多显示8位小数(精度为8)
break;
default:cout<<"error:unknown command "<<s<<endl;
break;
}
}
free(Ptr);
return 0;
}
中缀表达式转后缀表达式
#include<iostream>
#include<cstdlib>
#include<cctype>
using namespace std;
#define MaxSize 100 //堆栈元素的最大个数
#define MaxOP 100 //运算数序列可能的最大长度
typedef char ElementType; //将堆栈元素类型具体化
typedef struct SNode *Stack;
struct SNode{
ElementType data[MaxSize];
int top;
};
//建立空栈
Stack CreateStack()
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->top = -1;
return S;
}
//入栈
void Push(Stack PtrS,ElementType X)
{
if(PtrS->top==MaxSize-1)
cout<<"堆栈满"<<endl;
else
PtrS->data[++(PtrS->top)]=X;
}
//出栈
#define Error -1
ElementType Pop(Stack PtrS)
{
if(PtrS->top==-1){
cout<<"空栈"<<endl;
return Error;
}else{
return (PtrS->data[(PtrS->top)--]);
}
}
//优先级函数
int prior(char a)
{
if(a == '+' || a == '-')
return 1;
if(a == '*' || a == '/')
return 2;
}
//转换函数
void Transfer(char a[],Stack PtrS)
{
int i = 0;
while(1)
{
if(a[i] == '\0') //遇到结束符
{
if(PtrS->top == -1) //此时如果栈顶为空就返回
return;
else
//如果栈不为空则将栈内所有元素出栈
{
while(PtrS->top != -1)
{
cout<<Pop(PtrS)<<" ";
}
return;
}
}
else if(isdigit(a[i]))
//如果是数字则直接输出
{
while(isdigit(a[i])){ //当a[i]是数字时,则输出连续的数字
cout<<a[i];
i++;
}
if(a[i] == '.'){ //如果有小数点,则一直输出完小数点后的连续数字
cout<<a[i];
i++;
while(isdigit(a[i])){
cout<<a[i];
i++;
}
}
cout<<" ";
continue;
}
else if(PtrS->top == -1)
//如果不是数字,只能是运算符,判断此时堆栈有没有元素
//如果堆栈没有元素,将运算符压入堆栈
{
Push(PtrS,a[i]);
i++;
continue;
}
else if(a[i] == '(') //遇到左括号,直接压入堆栈
{
Push(PtrS,a[i]);
i++;
continue;
}
else if(a[i] == ')')
//遇到右括号,将堆栈中的元素弹出并输出,直到遇到左括号,最后将左括号弹出
//左括号不输出
{
while(PtrS->data[PtrS->top] != '(')
cout<<Pop(PtrS)<<" ";
Pop(PtrS);
i++;
continue;
}
else
//既不是左括号,也不是右括号,堆栈也不为空
//那么比较运算符与栈顶元素的优先级
{
while(1)
{
if(PtrS->top == -1 || prior(a[i]) > prior(PtrS->data[PtrS->top]) || PtrS->data[PtrS->top] == '(')
//如果栈顶为空或者优先级大于栈顶元素或者栈顶元素是左括号
//那么将元素压入堆栈
{
Push(PtrS,a[i]);
break;
}
else
{
cout<<Pop(PtrS)<<" "; //弹出一个元素并输出
}
}
i++;
continue;
}
}
return;
}
int main()
{
Stack Ptr = CreateStack();
char s[MaxOP];
cin>>s;
Transfer(s,Ptr);
free(Ptr);
return 0;
}