面向对象程序设计第四次作业

Github地址:点这里

主要内容:

  • 用栈对表达式进行处理 C++ STL--stack/queue 的使用方法
  • 对表达式进行计算(优先级及负数问题)

    具体实现

    本来自己没有丝毫头绪,在看过其他已经完成的同学的博客之后才了解到可以通过将中缀表达式变形为前缀表达式的方式方便计算机计算。于是百度,找到了用栈转换表达式形式以及计算的教程,于是接下来的工作就是按部就班,照着教程一步一步写,慢慢debug。其中碰到的负数问题也因为看过廖兴桔同学的博客而迎刃而解。

    代码

#include<string>
#include<queue>
#include<cctype>
#include<stack>
#include<sstream>
#include"Calculator.h"

using namespace std;

int Calculation::priority(char x)//比较优先级
{
    if (x == '+' || x == '-')
    {
        return 1;
    }
    else if (x == '*' || x == '/')
    {
        return 2;
    }
    else if (x == '(' || x == ')')
    {
        return 0;
    }
    else return 0;
}



void Calculation::compare(char m, string n, string q)
{
    char temp2 = n[0];
    if (Calculation::priority(m) >= Calculation::priority(temp2))//优先级比栈顶运算符的较高或相等,也将运算符压入栈1
    {
        m_S2.push(q);
    }
    else//否则将栈顶元素弹出并压入栈2,将新栈顶元素继续比较
    {
        m_S1.push(m_S2.top());
        m_S2.pop();
        if (!m_S2.empty())
        {
            compare(m, m_S2.top(), q);
        }
        else
        {
            string trans;
            trans += m;
            m_S2.push(trans);
        }
    }
}

int cal(int a, int b, char x)
{
    if (x == '+')
    {
        return a + b;
    }
    else if (x == '-')
    {
        return a - b;
    }
    else if (x == '*')
    {
        return a * b;
    }
    else if (x == '/')
    {
        if (b != 0)
        {
            return a / b;
        }
        else
        {
            printf("除数不能为零!");
            return 0;
        }
    }
    else return 0;
}



int Calculation::ToCalculate(queue<string>queue)
{
    int i;
    double num;
    string trans;
    char temp;
    string expression[101];
    for (i = 0; !queue.empty(); i++)//将表达式传入string
    {
        expression[i] = queue.front();
        queue.pop();
    }
    i--;
    for (; i >= 0; i--)//从右至左扫描表达式
    {
        trans = expression[i];
        temp = trans[0];
        if (!isdigit(temp) && temp != '(' && temp != ')')//如果是运算符
        {
            if (m_S2.empty() || m_S2.top() == ")")
            {
                m_S2.push(trans);//如果栈2空或者栈 顶为右括号,直接压入
            }

            else//否则需要与栈顶元素比较优先级
            {
                compare(temp, m_S2.top(), trans);
            }
        }

        else if (temp == '(')/*如果是左括号,依次弹出栈1顶的运算符,并压入栈2,
                             直到遇到右括号为止,此时将这对括号舍弃*/
        {
            while (m_S2.top() != ")")
            {
                m_S1.push(m_S2.top());
                m_S2.pop();
            };
            m_S2.pop();
        }

        else if (temp == ')')//如果是右括号,直接压入栈2中,
        {
            m_S2.push(trans);
        }
        
        else//数字存进另一个栈
        {
            m_S1.push(trans);
        }
    }

    while (!m_S1.empty())/*将栈1剩余的运算符依次弹出并压入栈2,栈2中即中缀
        表达式对应的前缀表达式倒叙*/
    {
        m_S2.push(m_S1.top());
        m_S1.pop();
    }
    string expression1[101];
    for (i = 0; !m_S2.empty(); i++)//将栈中倒序的表达式存入string中,接下来开始计算。
    {
        expression1[i] += m_S2.top();
        m_S2.pop();
    }
    int j = i;
    for (i = 0; i < j; i++)//从右至左扫描表达式
    {
        if (isdigit(expression1[i][0]))//遇到数字
        {
            stringstream stream(expression1[i]);
            stream >> num;
            m_S3.push(num);//压入栈中
        }
        else//遇到运算符
        {
            double temp1, temp2;
            temp1 = m_S3.top();
            m_S3.pop();
            temp2 = m_S3.top();
            m_S3.pop();
            double temp3 = cal(temp1, temp2, expression1[i][0]);//取出栈顶两个数字进行计算后压回栈中
            m_S3.push(temp3);
        }
    }
    return m_S3.top();//最后栈顶的数字就是答案
    m_S3.pop();
}

实现效果

886235-20160414205846238-1684856468.png

总结

  • 这次作业的完成应该是算站在大神的肩膀上,参考了许多很早就完成的同学的作业,学习他们的方法,在自己编写的过程中尽量学习使之成为自己的东西。
  • 通过这次作业学习了前中后缀表达式的转换以及sstream对字符串及整形进行转换。
  • 这一次的作业,虽然编写过程对我来说有一些困难,但是发现自己还蛮喜欢debug的,观察变量在调试过程中的变化情况,找到错误并修正能够给我带来一些成就感。
  • 其实每次在完成之后回头看,其实问题并没有一开始接手时感觉的那么困难,只要有了正确的方法,加上自己的耐心和思考,总是可以完成的。

转载于:https://www.cnblogs.com/Wjianting/p/5388561.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值