计算机软件实习项目1-科学计算器的实现


目录

 目录

实验内容

实验目的

编程语言和开发环境

实验步骤

实验核心


一、实验内容

1、学习图形界面的设计,利用 MFC 应用程序(Java swing 或 QT 框架,或 C#)创建基于对话框的应用程序,添加按钮、编辑框等控件。

2、能通过设计的按钮控件输入并实现简单算术运算,要求表达式在编辑框中显示,能将运算结果,输出在编辑框内显示;并保存历史的表达式运算记录。

3、能够正确实现算术表达式求解,是指算术表达式中包括加、减、乘、除、括号等运算符,能求解包含括号的四则混合运算,并且能够识别括号,优先级正确。

4、实现三角函数的运算、对数运算、指数运算、进制转换等。

二、项目目标

  1、能通过设计的按钮控件输入并实现简单算术运算,要求表达式在编辑框中显示,能将运算结 果,输出在编辑框内显示

  2、能够实现混合运算的求解,算术表达式中包括加、减、乘、除、括号等运算符;并且能够识别括号,优先级正确。

 3、能够保存历史的表达式运算记录以及三角函数的运算、对数运算、指数运算、进制转换等科学计数。

三、编程语言和开发环境

本次开发采用C++与QT结合的形式

四、实验步骤

        首先用QT建立一个如下图所示的UI界面,我是想做一个如图所示的科学计算器,其中下面的白色框input存储的是数字或者字,上面的白色框formula存储的是中缀表达式,按下等于号后则由中缀表达式转为后缀表达式。

        其次是在代码里运行各个按键的属性,考虑到分母不为0,后括号之前不能没有前括号的情况以及若是四个0则直接清楚只留下一个0,考虑各个部分的优先级。

        最后是界面跳转、历史记录特效等的整合。

五、实验核心

整个项目的核心点在于如何用双栈法求解中缀表达式转后缀表达式。

中缀表达式是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:a+b),中缀表达式是传统表达式也是人们常用的算术表示方法。而后缀表达式又称逆波兰式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)(例:ab+)。

中缀转后缀规则:利用双栈法,让操作符在一个栈,操作数在另一个栈。若后面一个符号比前面一个符号的优先级高,则后面一个符号入栈,若后面一个符号比前面一个符号的优先级低,则前面一个符号出栈。

算法思路:建立一个栈S。从左到右读表达式,如果读到操作数就将它压入栈S中,如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项按操作数运算,再将运算的结果代替原栈顶的n项,压入栈S中。如果后缀表达式未读完,则重复上面过程,最后输出栈顶的数值则为结束。

典型案例

后缀表达式:abcd/-e*+

  1. 扫描操作数abcd,并依次入栈
  2. 扫描到运算符 / ,d出栈,c出栈,计算c/d,再重新压入栈
  3. 扫描到运算符 - ,c/d出栈,b出栈,计算b-c/d,再重新压入栈

4、扫描操作数e,入栈​​​​​​

5、扫描到运算符 * ,e出栈,b-c/d 出栈,计算 (b-c/d)*e,再重新压入栈

6、扫描到运算符 + ,(b-c/d)*e 出栈,a出栈,计算 a+(b-c/d)*e ,再重新压入栈

此时栈顶的值就是后缀表达式abcd/-e*+的值。

 分离操作数和数代码

QQueue<QString> myCal::getMid(const QString& s) //分离操作数和运算符

{

    QQueue<QString> Q;  //分离后的操作数与运算符队列

    QString val="";     //操作数

    for(int i=0;i<s.length();i++)

    {

        if( (s[i]=='.') || ( (s[i]>='0') && (s[i]<='9') )) //判断小数点和数字

            val += s[i];

        else if(s[i]== '(' || s[i]== ')' || s[i]== '*' || s[i]== '/' || s[i] == '^' || s[i] == '%' )

        {

            if(!val.isEmpty()){

                Q.enqueue(val);                 //加入数字

                val.clear();                    //清空数字,等待下一个操作数

            }

            Q.enqueue(s[i]);                    //加入运算符

        }

        else if(s[i]== '+' || s[i]== '-')       //+,-号有两种情况,运算符或者正负号

        {

            if(i==0) val+= s[i];                //表达式第一个字符则是正负号

            else if(s[i-1]=='(' || s[i-1]=='+' || s[i-1]=='-' || s[i-1]=='*' || s[i-1]=='/'|| s[i-1] == '^' || s[i-1] == '%')

                val+= s[i];                     //括号或者运算符开头也是正负号

            else                                //其他情况则是加减运算符

            {

                if(!val.isEmpty())

                {

                    Q.enqueue(val);             //加入数字

                    val.clear();                //清空数字

                }

                Q.enqueue(s[i]);                //加入运算符

            }

        }

    }

    if(!val.isEmpty())                          //遍历完成,加入最后一个操作数

    {

        Q.enqueue(val);

        val.clear();

    }

    return Q;

}

中缀转后缀代码

QQueue<QString> myCal::getPost(QQueue<QString>& s)     //将中缀队列转换为后缀队列

{

    QStack<QString> st;

    QQueue<QString> Q;

    bool cheak;

    QString fuhao;

    while(!s.isEmpty())

    {

      fuhao = s.dequeue();      //取出一个字符

      fuhao.toDouble(&cheak);   //转换为字符串

      if(cheak==true)           //字符为数字

           st.push(fuhao);

      else if(fuhao=="+"||fuhao=="-")   //加减运算符

      {

          while(!st.isEmpty() &&(st.top()!="(")) //直到栈空或遇到左括号

              Q.enqueue(st.pop());     //由于优先级,先将其他运算符加入队列

          st.push(fuhao);        //此次运算符入栈

      }

      else if(fuhao=="*"||fuhao=="/"|| fuhao == "^" || fuhao == "%")

      {

          while(!st.isEmpty() && (st.top()!="(") && (st.top()!="+") && (st.top()!="-"))

              Q.enqueue(st.pop());//之前的同优先级运算符入队列

          st.push(fuhao);         //此次运算符入栈

      }

      else if(fuhao == "(")       //左括号入栈

         st.push(fuhao);

      else if(fuhao ==")")        //右括号

      {

          while(!st.isEmpty() && (st.top()!="("))

              Q.enqueue(st.pop());//括号里运算符入队列

          if(st.top()=="(")       //去掉左括号

            st.pop();

      }

    }

    while(!st.isEmpty()&& (st.top()!="("))//遍历完成,加入最后一个运算符

       Q.enqueue(st.pop());

    return Q;

}

后缀表达式求值

QString myCal::calExp(QQueue<QString>& s)//计算后缀表达式

{

    QStack<QString> st;

    QString fuhao,l,r,result;

    bool check;

    while(!s.isEmpty())

    {

      fuhao = s.dequeue();      //取出一个字符串

      fuhao.toDouble(&check);

      if(check==true)           //数字则入栈等待计算

        st.push(fuhao);

      else                      //运算符则进行计算

      {

          if(st.size()<2) return "wrong";//操作数不足两个

          r= st.pop();          //取出两个数字进行计算

          l= st.pop();

          result = calTwoOper(l,fuhao,r );//得到计算结果

          if(result==NULL) return result; //除数为零

          st.push(result);      //加入计算结果,等待后续计算

      }

    }

    if(st.size()==1) //计算完成,结果唯一

         return resultCorrect(st.pop());

    else return "wrong";

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值