黑龙江大学《数据结构与算法》实验六 表达式求值问题

 一般的运算式都是中缀表达式,顺序扫描中缀表达式,当读到数字时,直接将其送至输出队列中;当读到运算符时,将 运算符栈中所有优先级高于或等于当前运算符的运算符弹出,送至输出队列中,再将当前运 算符入栈;当读入左括号时,将其入运算符栈;当读到右括号时,将运算符符栈中从栈顶到 靠近栈顶的第一个左括号(“伪栈底”)之间的所有运算符全部依次弹出,送至输出队列中, 再删除栈中的左括号。 为了简化算法,可认为扫描到的任何运算符,其优先级都比栈顶的左括号优先级高。为 了方便边界条件(栈空)判断,提高算法运行效率,在扫描中缀表达式之前,在空栈中预先 压入一个‘#’字符作为栈底元素,另外,在中缀表达式的最后增加一个‘#’字符作为中缀 表达式的结束标志,当扫描到结束符‘#’时,将栈中从栈顶到‘#’之间的所有运算符全部 依次弹出,送至输出队列中,再删除栈中的‘#’,并结束算法。 除了显示算法的运行结果外,最好能在算法运行过程中演示运算符栈和存放后缀表达式 的队列的变化情况。如,若输入的中缀表达式字符串: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;
}

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值