//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
}
}