MFC使用雙棧實現簡單計算器

//2013.5.24

//數據結構,中石大,cakeman

//使用操作數棧和操作符棧,計算表達式的值

//運行界面

源文件下載地址:http://download.csdn.net/detail/ye_xingren/5468657

 

 

關鍵代碼:

void CCalculaterDlg::OnCal()
{

 // TODO: Add your control notification handler code here
 CString StrErr;//提示錯誤
 bool m_Legal=false;
 if(m_exp.IsEmpty())
 {
  StrErr="請輸入表達式!";
  MessageBox(StrErr);
  return;
 }
 char op='#';
 
 
 op=m_exp.GetAt(0);//m_exp爲表達式字符串
 if (!IsOperand(op))//判操作數否
 {
  switch(op)
  {
  case '(':
  case '-':
   break;
  default:
   {
    StrErr="不能以不合法運算符開頭(包括‘+’)";
    MessageBox(StrErr);
    m_exp="";
    SetDlgItemText(IDC_EXP,m_exp);
    return;
   }
  }
 }
 op=m_exp.GetAt(m_exp.GetLength()-1);
 if (!IsOperand(op))
 {
  switch(op)   
  {   
  case ')':   
   break;   
  default:   
   {    
    StrErr="不能以運算符結尾!";
    MessageBox(StrErr);
    m_exp="";
    SetDlgItemText(IDC_EXP,m_exp);
    return;    
   }                              
  }
 }
 for (int i=0;i<m_exp.GetLength()-1;i++)
 {
  op=m_exp.GetAt(i);
  char cp;
  if (cp=m_exp.GetAt(i),m_exp.GetLength()==1&&isp(cp)>=0&&icp(cp)>=0)
  {
   StrErr="僅運算符無法計算!";
   MessageBox(StrErr);
   m_exp="";
   SetDlgItemText(IDC_EXP,m_exp);
   return;
  }
  else  if (isp(op)>0&&isp(op)<6&&icp(op)>0&&icp(op)<6)
  {
   if (cp=m_exp.GetAt(i+1),isp(cp)>0&&isp(cp)<6&&icp(cp)>0&&icp(cp)<6)
   {
    StrErr="兩運算符間無運算數,請檢查表達式!";
    MessageBox(StrErr);
    m_exp="";
    SetDlgItemText(IDC_EXP,m_exp);
    return;
   }
  }
  m_Legal=true;
  
 }
 if(m_Legal)
 Calculate(m_exp);
}

 

void CCalculaterDlg::Calculate(CString exp)
{
 stack<char> s;
 char op='#',ch='#';//ch當前到來字符,op操作符棧頂元素 
 stack<char> optr;//操作符棧 
 optr.push(op);
 
 stack<double> opnd;//操作數棧 
 double  opndTop=0.0,opndTop2=0.0;
 char optrTop;//棧頂元素
 int left=0,right=0;//左右括弧個數

 exp+="#";
 //optrTop=optr.top();
 //AfxMessageBox(optrTop);

 int i=0,j=0;//計數器

 for (i=0,op=exp.GetAt(i);i<exp.GetLength();i++)//掃描表達式檢查匹配括號
 {
  op=exp.GetAt(i);
  if(isp(op)==1&&icp(op)==6)
   left++;
  if(isp(op)==6&&icp(op)==1)
   right++; 
 }
 if(left!=right)
 {
  MessageBox("括號不匹配!請檢查表達式");
  m_exp="";
  SetDlgItemText(IDC_EXP,m_exp);
  return;
 }
 /*for (int i=0,op=exp.GetAt(i);i<exp.GetLength();i++)
 {
  if (isp(op)==-1)
  {
   opnd.push(int(op-'0'));
   if ()
   {
   }
  }
 }*/
 CString opndStr;
 double opndNum;
 
 i=0;
 ch=exp.GetAt(i);

 while (optr.empty()==false)
 {
  ch=exp.GetAt(i);
  if (IsOperand(ch))
  {    
   for(j=i;j<exp.GetLength();j++)
   {
    if (!IsOperand(exp.GetAt(j)))
     break;
   }
   opndStr=exp.Mid(i,j-i);
   opndNum=atof(opndStr);
   opnd.push(opndNum);//轉換爲操作數後壓入棧中

   i=j;//從j元素處開始檢測
  }
  else
  {
   optrTop=optr.top();//取操作符棧頂元素
   if (isp(optrTop)<icp(ch))//新讀入操作符優先級高
   {
    optr.push(ch);
    i++;
   }
   else if (isp(optrTop)>icp(ch))//新讀入操作符優先級低
   {
    op=optr.top();
    optr.pop();
    opndTop=opnd.top();
    opnd.pop();
    opndTop2=opnd.top();
    opnd.pop();
    opnd.push(GetResult(opndTop2,opndTop,op));
   }
   else{
    op=optr.top();
    optr.pop();
    if(op=='(')
     i++;
   }
  }
 }
 //dlg.SetDlgItemText(IDC_EDIT_Res,)
 //Result dlg;
 CString res;
 res.Format(_T("%lf"),opnd.top());
 //dlg.DoModal();
 SetDlgItemText(IDC_Result,res);
 
 
}

bool CCalculaterDlg::IsOperand(char ch)
{
 if ((ch>='0'&&ch<='9')||ch=='.')
 {
  return true;
 }
 else return false;
}

int CCalculaterDlg::isp(char ch)
{
 switch(ch)
 {
 case '#':
  return 0;
  break;
 case '(':
  return 1;
  break;
 case '*':
  return 5;
  break;
 case '/':
  return 5;
  break;
 case '%':
  return 5;
  break;
 case '+':
  return 3;
  break;
 case '-':
  return 3;
  break;
 case ')':
  return 6;
  break;
 default:
  return -1;
 }

}

int CCalculaterDlg::icp(char ch)
{
 switch(ch)
 {
 case '#':
  return 0;
  break;
 case '(':
  return 6;
  break;
 case '*':
  return 4;
  break;
 case '/':
  return 4;
  break;
 case '%':
  return 4;
  break;
 case '+':
  return 2;
  break;
 case '-':
  return 2;
  break;
 case ')':
  return 1;
  break;
 default:
  return -1;
 }
}

double CCalculaterDlg::GetResult(double a, double b, char c)
{
 switch (c)
 {
 case '*':
  return a*b;
  break;
 case '/':
  return a/b;
  break;
 case '+':
  return a+b;
  break;
 case '-':
  return a-b;
  break;
 default:
  exit(-1);//Error
 }
}

 

發佈了27 篇原創文章 · 獲贊 11 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章