一般的运算式都是中缀表达式,顺序扫描中缀表达式,当读到数字时,直接将其送至输出队列中;当读到运算符时,将 运算符栈中所有优先级高于或等于当前运算符的运算符弹出,送至输出队列中,再将当前运 算符入栈;当读入左括号时,将其入运算符栈;当读到右括号时,将运算符符栈中从栈顶到 靠近栈顶的第一个左括号(“伪栈底”)之间的所有运算符全部依次弹出,送至输出队列中, 再删除栈中的左括号。 为了简化算法,可认为扫描到的任何运算符,其优先级都比栈顶的左括号优先级高。为 了方便边界条件(栈空)判断,提高算法运行效率,在扫描中缀表达式之前,在空栈中预先 压入一个‘#’字符作为栈底元素,另外,在中缀表达式的最后增加一个‘#’字符作为中缀 表达式的结束标志,当扫描到结束符‘#’时,将栈中从栈顶到‘#’之间的所有运算符全部 依次弹出,送至输出队列中,再删除栈中的‘#’,并结束算法。 除了显示算法的运行结果外,最好能在算法运行过程中演示运算符栈和存放后缀表达式 的队列的变化情况。如,若输入的中缀表达式字符串:1+2*(3-1+2)-3#,就会得到后缀表 达式:1231-2+*+3-,在算法运行过程中,运算符栈和存放后缀表达式的队列变化过程如表 1 所示。
void Infixtosuffix(string expression)
{
gotoxy(25,10);
cout<<"输出将中缀转换成后缀后得到的表达式:";
string s=expression;
char fu[100];
y.clear();
int top1=-1;
top2=-1;
top1++;
fu[top1]='#';
for(int i=0;i<s.size()-1;i++)
{
if(s[i]>='0'&&s[i]<='9')
{
top2++;
y[top2]=s[i];
}
else
{
if(s[i]=='+')
{
if(top1>=1)
{
while(fu[top1]=='+'||fu[top1]=='-'||fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='-')
{
if(top1>=1)
{
while(fu[top1]=='+'||fu[top1]=='-'||fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='*')
{
if(top1>=1)
{
while(fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='/')
{
if(top1>=1)
{
while(fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='(')
{
top1++;
fu[top1]=s[i];
}
else if(s[i]==')')
{
if(top1>=1)
{
while(fu[top1]!='(')
{
top2++;
y[top2]=fu[top1];
top1--;
}
top1--;
}
}
}
}
while(top1!=0)
{
top2++;
y[top2]=fu[top1];
top1--;
}
for(int i=0;i<=top2;i++)cout<<y[i];
gotoxy(25,11);
cout<<"按任意键返回菜单:";
getch();
system("cls");
menu(expression);
}
后缀表达式的计算
利用栈(操作数和运算结果栈)计算后缀表达式。顺序扫描后缀表达式,当读到数字时, 将其送至栈中;当读到运算符 θ 时,将栈顶字符弹出,将其转换成对应的数值并赋给变量 y, 再将次栈顶字符弹出,将其转换成对应的数值,并赋给变量 x,之后计算 xθy,将运算结果转 换成对应的数字字符送入栈中。 本算法可以对任意输入的后缀表达式进行计算,也可以以前一个中缀表达式到后缀表达 式转换算法的输出为输入,计算该后缀表达式。 除了显示算法的运行结果外,最好能在算法运行过程中演示(操作数和运算结果)栈的 变化情况。以输入的后缀表达式为 1231-2+*+3-的情况为例,在算法运行过程中,操作数及运 算结果栈变化过程如表 2 所示。
void Calculationsuffixexpression()
{
if(top2==-1)
{
gotoxy(30,10);
cout<<"中缀表达式还未转换成后缀表达式"<<endl;
}
else{
int cal[100];//建立个栈用来存数计算后缀表达式
int top=-1;//表示栈顶
for(int i=0;i<=top2;i++)
{
if(y[i]>='0'&&y[i]<='9')
{
top++;
cal[top]=y[i]-'0';
}
else
{
int num=cal[top];
top--;
if(y[i]=='+')cal[top]=cal[top]+num;
else if(y[i]=='-')cal[top]=cal[top]-num;
else if(y[i]=='*')cal[top]=cal[top]*num;
else if(y[i]=='/'&&num!=0)cal[top]=cal[top]/num;
}
}
gotoxy(30,10);
cout<<"输出计算结果:";
cout<<cal[top];
}
gotoxy(30,11);
cout<<"按任意键返回菜单:";
getch();
system("cls");
menu(ss);
}
中缀的计算比较抽象,只可意会不可言传,这里就不多说了,怕误了大家。
这次实验有两个项目,这里是关于表达式求值的,我的实验偏向于意识流,代码长只可意会不可言传,本人又菜写的bug又多,发出来仅供参考,能自己写最好。
#include <iostream>
#include<bits/stdc++.h>
#include<windows.h>
#include<conio.h>
using namespace std;
string ss;//全局变量用于输入中缀表达式
string y;//全局变量用于储存后缀表达式
int top2=-1;//全局变量用于记录后缀表达式的长度
void gotoxy(int x, int y);//更新光标位置,用于打印菜单
void sscanf();//输入表达式
void Interface();//打印菜单
void Infixtosuffix(string expression);//将中缀表达式转换成后缀表达式
void Calculationsuffixexpression();//计算后缀表达式
void Computeinfixexpression();//计算中缀表达式
void menu();//菜单选择
void gotoxy(int x, int y)
{
// 更新光标位置
COORD pos;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(hOutput, pos);//两个参数分别是指定哪个窗体,具体位置
// 隐藏光标
CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = sizeof(cursor);
SetConsoleCursorInfo(hOutput, &cursor);
}
void Interface()//打印菜单
{
gotoxy(30,5);
cout<<"------------------------------------------------------";
gotoxy(50,6);
cout<<"表达式求值";
gotoxy(30,7);
cout<<"1. 中缀表达式到后缀表达式的转换";
gotoxy(30,8);
cout<<"2. 后缀表达式的计算";
gotoxy(30,9);
cout<<"3. 中缀表达式的计算";
gotoxy(30,10);
cout<<"4. 退出";
gotoxy(30,11);
cout<<"5. 重新输入算数表达式";
gotoxy(30,12);
cout<<"-------------------------------------------------------";
}
void menu(string expression)
{
Interface();
gotoxy(30,13);
cout<<"输入选择:";
int choice;
cin>>choice;
system("cls");
switch(choice)
{
case 1:
{
Infixtosuffix(expression);
break;
}
case 2:
{
Calculationsuffixexpression();
break;
}
case 3:
{
Computeinfixexpression();
break;
}
case 4:
{
gotoxy(50,10);
cout<<"运算结束"<<endl;
break;
}
case 5:
{
sscanf();
break;
}
}
}
void Infixtosuffix(string expression)
{
gotoxy(25,10);
cout<<"输出将中缀转换成后缀后得到的表达式:";
string s=expression;
char fu[100];
y.clear();
int top1=-1;
top2=-1;
top1++;
fu[top1]='#';
for(int i=0;i<s.size()-1;i++)
{
if(s[i]>='0'&&s[i]<='9')
{
top2++;
y[top2]=s[i];
}
else
{
if(s[i]=='+')
{
if(top1>=1)
{
while(fu[top1]=='+'||fu[top1]=='-'||fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='-')
{
if(top1>=1)
{
while(fu[top1]=='+'||fu[top1]=='-'||fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='*')
{
if(top1>=1)
{
while(fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='/')
{
if(top1>=1)
{
while(fu[top1]=='*'||fu[top1]=='/'||fu[top1]==')')
{
top2++;
y[top2]=fu[top1];
top1--;
}
}
top1++;
fu[top1]=s[i];
}
else if(s[i]=='(')
{
top1++;
fu[top1]=s[i];
}
else if(s[i]==')')
{
if(top1>=1)
{
while(fu[top1]!='(')
{
top2++;
y[top2]=fu[top1];
top1--;
}
top1--;
}
}
}
}
while(top1!=0)
{
top2++;
y[top2]=fu[top1];
top1--;
}
for(int i=0;i<=top2;i++)cout<<y[i];
gotoxy(25,11);
cout<<"按任意键返回菜单:";
getch();
system("cls");
menu(expression);
}
void Calculationsuffixexpression()
{
if(top2==-1)
{
gotoxy(30,10);
cout<<"中缀表达式还未转换成后缀表达式"<<endl;
}
else{
int cal[100];//建立个栈用来存数计算后缀表达式
int top=-1;//表示栈顶
for(int i=0;i<=top2;i++)
{
if(y[i]>='0'&&y[i]<='9')
{
top++;
cal[top]=y[i]-'0';
}
else
{
int num=cal[top];
top--;
if(y[i]=='+')cal[top]=cal[top]+num;
else if(y[i]=='-')cal[top]=cal[top]-num;
else if(y[i]=='*')cal[top]=cal[top]*num;
else if(y[i]=='/'&&num!=0)cal[top]=cal[top]/num;
}
}
gotoxy(30,10);
cout<<"输出计算结果:";
cout<<cal[top];
}
gotoxy(30,11);
cout<<"按任意键返回菜单:";
getch();
system("cls");
menu(ss);
}
void Computeinfixexpression()
{
int num[100];//存数字的栈
char fu[100];//存符号的栈
int t1=-1;//数字栈的栈顶初始为-1
int t2=-1;//符号栈的栈顶初始为-1
t2++;
fu[t2]='#';
for(int i=0;i<ss.size();i++)
{
if(ss[i]>='0'&&ss[i]<='9')
{
t1++;
num[t1]=ss[i]-'0';
}
else
{
if(ss[i]=='+'||ss[i]=='-')
{
if(t2>0)
{
if(fu[t2]=='+')
{
int k=num[t1];
t1--;
num[t1]+=k;
t2--;
}
else if(fu[t2]=='-')
{
int k=num[t1];
t1--;
num[t1]-=k;
t2--;
}
else if(fu[t2]=='*')
{
int k=num[t1];
t1--;
num[t1]*=k;
t2--;
}
else if(fu[t2]=='/'&&num[t1]!=0)//除法可能需要特判一下0,但是只要不闲的没事输入0应该就没有问题了(解决不了问题就解决提出问题的人)
{
int k=num[t1];
t1--;
num[t1]/=k;
t2--;
}
}
t2++;
fu[t2]=ss[i];
}
else if(ss[i]=='*'||ss[i]=='/')
{
if(t2>0)
{
if(fu[t2]=='*')
{
int k=num[t1];
t1--;
num[t1]*=k;
t2--;
}
else if(fu[t2]=='/'&&num[t1]!=0)//除法可能需要特判一下0,但是只要不闲的没事输入0应该就没有问题了(解决不了问题就解决提出问题的人)
{
int k=num[t1];
t1--;
num[t1]/=k;
t2--;
}
}
t2++;
fu[t2]=ss[i];
}
else if(ss[i]=='(')
{
t2++;
fu[t2]=ss[i];
}
else if(ss[i]==')')
{
while(fu[t2]!='(')
{
if(t2>1)
{
if(fu[t2]=='+')
{
int k=num[t1];
t1--;
num[t1]+=k;
t2--;
}
else if(fu[t2]=='-')
{
int k=num[t1];
t1--;
num[t1]-=k;
t2--;
}
else if(fu[t2]=='*')
{
int k=num[t1];
t1--;
num[t1]*=k;
t2--;
}
else if(fu[t2]=='/'&&num[t1]!=0)
{
int k=num[t1];
t1--;
num[t1]/=k;
t2--;
}
}
}
t2--;
if(t2>1)
{
if(fu[t2]=='+')
{
int k=num[t1];
t1--;
num[t1]+=k;
t2--;
}
else if(fu[t2]=='-')
{
int k=num[t1];
t1--;
num[t1]-=k;
t2--;
}
else if(fu[t2]=='*')
{
int k=num[t1];
t1--;
num[t1]*=k;
t2--;
}
else if(fu[t2]=='/'&&num[t1]!=0)
{
int k=num[t1];
t1--;
num[t1]/=k;
t2--;
}
}
}
else if(ss[i]=='#')
{
while(fu[t2]!='#')
{
if(fu[t2]=='+')
{
int k=num[t1];
t1--;
num[t1]+=k;
t2--;
}
else if(fu[t2]=='-')
{
int k=num[t1];
t1--;
num[t1]-=k;
t2--;
}
else if(fu[t2]=='*')
{
int k=num[t1];
t1--;
num[t1]*=k;
t2--;
}
else if(fu[t2]=='/'&&num[t1]!=0)
{
int k=num[t1];
t1--;
num[t1]/=k;
t2--;
}
}
}
}
}
gotoxy(30,10);
cout<<"输出计算结果:";
cout<<num[0];
gotoxy(30,11);
cout<<"按任意键返回菜单:";
getch();
system("cls");
menu(ss);
}
void sscanf()//输入算数表达式
{
ss.clear();
gotoxy(42,13);
cout<<"输入算数表达式:";
cin>>ss;
system("cls");
menu(ss);
}
int main()
{
system("color b");//(整活)给字体换个颜色
sscanf();
return 0;
}