首页
社区
课程
招聘
[原创]四则混合运算的计算
发表于: 2009-9-22 16:02 5523

[原创]四则混合运算的计算

2009-9-22 16:02
5523

大家好啊,好久没来看雪了,嘿嘿。关于四则运算,网上有很多源代码,而这一个是我自己写出来的,分享给大家吧:
  1、支持加减乘除
  2、支持括号运算,当然是(),其他乱成八糟的括号不认识
   3、能识别括号匹配
  4、支持负数,浮点数,整数运算

  主要思路是:
  A、将中缀表达式转化为后缀表达式
  B、用后缀表达式进行四则运算
  
  嘿嘿,还记得以前用VBS调用ScriptControl控件计算简单四则混合运算被大家取笑的事……

  

  呵呵,现在都是面向对象,用一个CExp类完成主要的功能:
              ////m_calc是CExp类的成员,负责计算
           CString s;
        GetDlgItemText(IDC_EDIT1, s);
        m_calc.SetMidExp(s.GetBuffer(0));
        if (m_calc.Mid2BackExp()){
                SetDlgItemText(IDC_EDIT2, m_calc.GetResult());
                double d = m_calc.calcResult();
                s.Format("%.3f", d);
                SetDlgItemText(IDC_EDIT3, s);
        }
        else{
                AfxMessageBox("你输入的表达式有问题!");
        }
    当然,这代码还存在着很多不足,比如,除数为零判断,比如其他函数计算如SIN,COS等,嘿嘿,不过如果大家能修定得更加完善,那本人的目的也达到了,利人利已!希望大家多多指教!

对于Mid2BackExp()函数作一下修改:
测试中发现 3+2-5*0-2 算出结果为7,与实际不符合,仔细分析后发现,如果是加减法,除非遇到(,或者栈为空,可以入栈,其它的运算符必须全部出来!

整个函数如下:
BOOL CExp::Mid2BackExp()//中缀表达式转后缀式
{
        // 1、如果是数字则直接放入后缀表达式数组;
        // 2、如果是左括号则直接入栈;
        // 3、如果是右括号,则把从栈顶直到对应左括号之间的运算符依次退栈,并清除对应的左括号;
        // 4、对于运算符,如果该运算符的优先级大于栈顶优先级,则直接入栈,若该运算符的优先级小于等于栈顶优先级,则先把栈顶运算符出栈,写入后缀表达式数组,然后再入栈;
        // 5、扫描完成后,取出栈中所有运算符,写入后缀表达式数组。
       
        int nLastIndex;
        int nLen = m_midExp.GetLength();
        if (0 >= nLen) return FALSE; //啥也没有转个屁啊!
        m_bkExp.Empty(); //首先将后缀表达式数组清空
        if (! IsBracketMatched()){ //括号不匹配也不转!
                return FALSE;
        }
               
        for(int i=0; i<nLen; i++){
                char c = m_midExp.GetAt(i);
                if (c >= '0' && c <= '9' || '.' == c || '-' == c){ //如果是数字,直接放入后缀表达式数组,小数点也算进来
                        if (c == '-'){ //负数的情况
                                if (m_stkOper.empty()){ //不含括号的情况
                                        if (m_bkExp.IsEmpty()){ //如果后缀数组也为空,那肯定是负数了!,对应 "-xx" 的情况
                                                m_bkExp += c;
                                                continue;
                                        }
                                }
                                else{
                                        if ('(' == m_stkOper.top()){ //对于含括号的情况,第一个是负数
                                                //如果后缀数组最后一位不是数字,那肯定是负数 ,对应 "(-(" 的情况
                                                nLastIndex = m_bkExp.GetLength()-1;
                                                if (nLastIndex>= 0){
                                                        if (! isdigit(m_bkExp.GetAt(nLastIndex))){
                                                                m_bkExp += c;
                                                                continue;
                                                        }
                                                }
                                                else{ //后缀数组里没内容,对应 "(-xx" 的情况
                                                        m_bkExp += c;
                                                        continue;
                                                }
                                        }
                                }
                        }
                        else{ //其他情况
                        m_bkExp += c;
                        continue;
                        }
                }
                nLastIndex = m_bkExp.GetLength();
                if (nLastIndex != 0) {
                        nLastIndex--;
                        if (',' != m_bkExp.GetAt(nLastIndex)) m_bkExp += ',';
                }
                //如果是运算符的话...
                switch(c){
                        case '+':
                        case '-':
                                        if (!m_stkOper.empty()) //+-法的优先级小于等于同级算法和乘除法 直接弹出所有非括号的运算符!
                                        {
                                                while(!m_stkOper.empty()){
                                                        if('(' != m_stkOper.top()){
                                                                m_bkExp += m_stkOper.top();
                                                                m_bkExp += ',';
                                                                m_stkOper.pop();
                                                        }
                                                        else{ //遇到了括号,就结束
                                                                break;
                                                        }
                                                }
                                                m_stkOper.push(c);
                                        }                               
                                        else{ //如果栈中无元素,直接入栈
                                                m_stkOper.push(c);
                                        }
                                        break;
                        case '*':
                        case '/':
                                //如果比栈顶元素优先级大,则入栈,否则同上
                                if ( !m_stkOper.empty()){
                                        switch(m_stkOper.top()){
                                                case '+':
                                                case '-':
                                                case '(': //加减法不能欺负,括号又欺负不了,直接入栈吧!
                                                        m_stkOper.push(c);
                                                        break;
                                                case '*':
                                                case '/': //同级的就弹出去!
                                                        m_bkExp += m_stkOper.top();
                                                        m_bkExp += ',';
                                                        m_stkOper.pop();
                                                        m_stkOper.push(c);
                                        }
                                }
                                else{//如果栈中无元素,直接入栈
                                        m_stkOper.push(c);
                                }
                                break;

                        case '(': //左括号直接入栈
                                m_stkOper.push(c);
                                break;

                        case ')':
                                while(m_stkOper.top()!='('){//弹出两括号之间的所有符号
                                        m_bkExp += m_stkOper.top();
                                        m_bkExp += ',';
                                        m_stkOper.pop();
                                }
                                m_stkOper.pop(); //弹出左括号       
                }
        }
        while(!m_stkOper.empty()){
                nLastIndex = m_bkExp.GetLength()-1;
                if (',' != m_bkExp.GetAt(nLastIndex)) m_bkExp += ',';
                m_bkExp += m_stkOper.top();
                m_stkOper.pop();
                m_bkExp += ',';
        }
        return TRUE;
}

将混合运算已经封装成dll文件,函数原型

double __stdcall ExpressStrCalc (LPCTSTR sExp);

在VB/VC下调用测试成功!


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (1)
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
2
呵呵,支持一下吧,以前上学的时候也写过类似的
2009-9-24 12:01
0
游客
登录 | 注册 方可回帖
返回
//