C++:表达式翻译

这篇博客介绍了如何使用C++编写程序将中缀表达式转换为后缀表达式,并根据后缀表达式计算数值。程序采用链栈数据结构,能处理包括逻辑和关系运算在内的复杂表达式。文章包含类的设计思路、部分核心代码以及测试运行的结果展示。
摘要由CSDN通过智能技术生成

课程设计中的题目,要求设计一个程序将输入中缀表达式转换成后缀表达式,再将根据后缀表达式计算出对应的数值,这也应该就是所谓的计算器在处理用户所输入的算式时,所作出的计算过程。


如:输入中缀表达式:(1+2)*3+4 ,计算器会将其转换为后缀表达式:1 2 + 3 * 4 +,其中去除了括号,然后计算器再根据特定的算法将其计算成数值:13。

这个程序就是类似的工作过程。其中使用到了链栈的数据机构,和基本的C++语法。


1.总体分析。

由于时间比较匆忙,所以程序的大多数算法和方法的设计都没有进行优化,但是主要功能齐全无误。而且不仅仅可以计算常规的四则运算,还可以混合逻辑运算的 “|”、“&”以及关系运算的 “>”、“<”、“=”一起进行运算。其中对于表达式的检测设计的不够详细,只是对其简单的进行判断,且方法较为冗余,仅供参考。


出了菜单之外,一共设计了两个类:

Stack:用来处理栈的各类操作。

Expression:用来实现表达式的具体转换过程和逻辑。

其中Expression类还可以再分为三个部分:中缀表达式转后缀表达式、后缀表达式转中缀表达式、后缀表达式计算数值。同样的,后来认为也可以将这三部分分开使用三个类的实现比较清晰。


2.部分代码构思。


首先是Stack类的设计。

class Stack
{
private:
    typedef struct StackNode//栈的节点
    {
        char data;//用来存放运算符数据
        int number;//用来存放数字
        struct StackNode *next;
    } StackNode;
    typedef struct StackLink//栈的头结点,用来存放栈的长度
    {
        StackNode *top;//指向栈顶
        int count;//统计栈的元素个数
    } StackLink;
public:
    StackLink SL;
    Stack()//初始化操作
    {
        CreateLink(SL);//创建一个空的链栈
    }

    void CreateLink(StackLink &SL)//初始化链栈
    {
        SL.count = 0;
        SL.top = NULL;
    }

    void pushElem(char ch)  //运算符入栈
    {
        StackNode* Q;//新的节点
        Q = (StackNode*)malloc(sizeof(StackNode));
        Q->data = ch;
        Q->next = SL.top;//让新的节点指向栈顶
        SL.top = Q;//指向栈顶
        SL.count++;
    }

    void pushElem(int number)//用于入栈数字
    {
        StackNode* Q;//新的节点
        Q = (StackNode*)malloc(sizeof(StackNode));
        Q->number = number;
        Q->next = SL.top;//让新的节点指向栈顶
        SL.top = Q;//指向栈顶
        SL.count++;
    }

    int popElemNumber()//出栈栈顶数值并返回
    {
        int num;
        StackNode* Q;
        Q = SL.top;//记录栈顶元素
        num = Q->number;
        SL.top = SL.top->next;//指向栈顶的下一个元素
        free(Q);//释放节点s
        SL.count--;
        return num;
    }

    void popElem()  //出栈
    {
        StackNode* Q;
        Q = SL.top;//记录栈顶元素
        SL.top = SL.top->next;//指向栈顶的下一个元素
        free(Q);//释放节点s
        SL.count--;
    }

    void destroyStack()//清空栈
    {
        while(SL.count != 0)
        {
            StackNode* Q;
            Q = SL.top;//记录栈顶元素
            SL.top = SL.top->next;//指向栈顶的下一个元素
            free(Q);//释放节点s
            SL.count--;
        }
    }
};

代码后面的注释较为齐全,总体来说就是实现了出栈操作和入栈操作、初始化栈和清空栈的操作。其中需要注意的是在这里重载了入栈的的方法,使其可以入栈char类型和int类型,这是因为后面需要两次用到这个栈来进行操作,并且入栈的类型不同,所以重载一下这个方法比较方便计算。


其次是Expression类。


先看一下类的属性:

private:
    string Z1;//用来存入中缀表达式
    char H2[100];//用来存入输入的后缀表达式
    char H3[100];//用来后缀计算数值
    char Z2[100];//用来保存后缀转中缀后的表达式
    char H1[100];//用来保存中缀转后缀表达式
    int zLength;//用来计算中缀表达式的长度
    int hLength;//用来计算后缀表达式的
    int houLength;//用来求数值的时候用的
    int number;//用来保存数值
    int zCount;//用来对中缀表达式进行处理
    int hCount;//用来对后缀表达式进行处理
    int houCount;//用来对后缀表达式进行部分处理
    Stack S1;//链栈,用来处理中缀转后缀
    Stack S2;//处理后缀计算数值

以后所出现的属性都在这里了,命名方面有些欠缺。


1)中缀表达式转后缀表达式。


首先需要输入中缀表达式,然后计算所输入内容的长度,用来后面的计算使用。

void setZ1()//输入中缀表达式
    {
        cout << "\n\n\n请输入中缀表达式:";
        cin >> Z1;
        ZLength();
    }
    void ZLength()//计算中缀表达式长度
    {
        zLength = 0;
        int i = 0;
        while(Z1[i] != '\0')
        {
            zLength++;
            i++;
        }
    }


其次是其中的核心代码:

int zToH()  //中缀转化为后缀
    {
        if(!checkBracket())
        {
            cout << "\n\n\n输入错误,括号不匹配!";
            return 0;
        }
        if(!checkOthers())
        {
            cout << "\n\n\n输入错误!";
            return 0;
        }
        zCount = 0;
        hCount = 0;
        char topCh;
        char nowCh;
        while(zCount < zLength)
        {
            //判断这个是数字还是运算符
            if(judgeNumOrAri(Z1[zCount]))  //如果是数字
            {
                H1[hCount] = Z1[zCount];//将数字存入到后缀字符中
                hCount++;//后缀下标+1
                nextChar(zCount,hCount);//判断这个数字的下一位是不是数字,直到遇到符号结束
                H1[hCount] = ' ';//用空格分隔开数字
                hCount++;
            }
            else    //如果是运算符
            {
                if(S1.SL.count == 0)//此时为空栈
                {
                    S1.pushElem(Z1[zCount]);//将运算符入栈
                }
                else//不为空栈的话需要判断此时的运算符与栈顶元素的运算符优先级,以及出栈的操作
                {
                    topCh = S1.SL.top->data;//取得此时栈顶元素的运算符
                    nowCh = Z1[zCount];//取得此时中缀表达式中的运算符
                    if(nowCh=='(')//如果是左括号的话,直接压栈
                    {
                        S1.pushElem(Z1[zCount]);
                    }
                    else//如果是其他符号的话,需要进行比较了
                    {
                        if(nowCh==')')//如果是右括号
                        {
                            while(topCh!='(' && S1.SL.count!=0)//如果栈顶符号不是左括号或者空,一直出栈
                            {
                                H1[hCount] = topCh;//将栈顶元素 赋值给后缀表达式
                                hCount++;
                                H1[hCount] = ' ';//用空格分隔开数字
                                hCount++;
                                S1.popElem();//栈顶元素出栈
                                if(S1.SL.top != NULL)
                                {
                                    topCh = S1.SL.top->data;
                                }
                            }
                            if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值