大家好啊,好久没来看雪了,嘿嘿。关于四则运算,网上有很多源代码,而这一个是我自己写出来的,分享给大家吧:
  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下调用测试成功!

上传的附件 express.rar