利用栈完成算术表达式求值: 从键盘或文件中输入算术表达式,计算其结果并显示。 (1)转换为后缀表达式并输出;
(2)对后缀表达式求值并输出。
输入的表达式中可以有整数、实数、括号,运算符包括+、-、*、/、#(代表单目负)。可以多次输入不同的表达式进行计算,直到用户选择“退出”。
对于以上该计算器,我们可以先使用一个栈暂时存储操作符,最后用一个数组来保存后缀表达式;之后根据后缀表达式利用栈计算即可得到最终的答案。OK,上代码:
/**
* p_calc.h: 类的设计主要为内部接口函数的声明
*/
#ifndef _P_CALC_H_
#define _P_CALC_H_
#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <cctype> //isdigit()
#include <cstdlib> //atof()
using namespace std;
class Calc
{
public:
Calc (string s_opers) : opers(s_opers) {}
// 用来判断后缀表达式是否能够成功转化
bool to_postfixExpression ();
// 计算
double pCalc();
double pCalc(double left, double right, char optr);
// 判断是否是操作符:'+'、'-'、'*'、'/'
bool isp_Optr(char c);
// 优先级判断
bool isp_notLow(char a, char b);
private:
string opers;
vector<string> pev;
};
#endif // _P_CALC_H_
/**
* p_calc.cpp: 头文件中的接口的实现
*/
#include "p_calc.h"
//转化为后缀表达式
bool Calc::to_postfixExpression ()
{
///前期判断
char tc = opers[0];
if (!isdigit(tc) && tc != '#' && tc != '(' )
return false;
string st = "";
stack <char> pes;
int i = 0, j = 0, length = opers.length();
while (i < length)
{
if (isdigit(opers[i]))
{
j = i;
while (i++ < length && isdigit(opers[i] )) {}
if(i < length && opers[i] == '.')
{
if (!isdigit(opers[i+1]))
return false;
while (i++ < length && isdigit(opers[i])) {}
}
pev.push_back(opers.substr(j, i-j));
//cout << "数字子串:" << opers.substr(j, i-j) << " j is: " << j << " i is: " << i << endl;
}
else if (isp_Optr(opers[i]))
{
if (isp_Optr(opers[i+1]) || opers[i+1] == '.')
return false;
if (!pes.empty() && pes.top() == '#')
{
pev.push_back("#");
pes.pop();
}
while (!pes.empty() && (isp_notLow(pes.top(), opers[i])))
{
pev.push_back(st+pes.top());
pes.pop();
}
pes.push(opers[i++]);
}
else if (opers[i] == '(')
{
if (isp_Optr(opers[i+1]))
return false;
pes.push(opers[i++]);
//cout << "i is: " << i << " ";
}
else if (opers[i] == ')')
{
while (pes.top() != '(')
{
pev.push_back(st+pes.top());
pes.pop();
}
pes.pop();
i++;
//cout << "i is: " << i << " ";
}
else if (opers[i] == '#')
{
if (isp_Optr(opers[i+1]))
return false;
pes.push(opers[i++]);
}
}
while (!pes.empty())
{
pev.push_back(st+pes.top());
pes.pop();
}
vector<string> :: iterator it;
cout << endl;
for (it = pev.begin(); it != pev.end(); it++)
cout << *it << " ";
cout << endl << endl;
return true;
}
利用后缀表达式来计算值
double Calc::pCalc()
{
stack<double> pcalcs;
for (vector<string> :: iterator it = pev.begin(); it != pev.end(); it++)
{
if (isdigit((*it)[0]))
pcalcs.push( atof( (*it).c_str() ) );
else if (isp_Optr((*it)[0]))
{
double right = pcalcs.top(); pcalcs.pop();
double left = pcalcs.top(); pcalcs.pop();
pcalcs.push( pCalc( left, right, (*it)[0] ) );
}
else if ( *it == "#" )
{
double dt = pcalcs.top(); pcalcs.pop();
pcalcs.push(-dt);
}
}
double final_answer = pcalcs.top(); pcalcs.pop();
if (pcalcs.empty())
return final_answer;
else
return 0;
}
double Calc::pCalc(double left, double right, char optr)
{
double answer;
switch (optr) {
case '+': answer = left + right; break;
case '-': answer = left - right; break;
case '*': answer = left * right; break;
case '/': answer = left / right; break;
//case '%': (int)answer = (int)left % (int)right; break;
}
return answer;
}
bool Calc::isp_Optr(char c)
{
return (c == '+' || c == '-' || c == '*' || c == '/'); // || c == '%');
}
bool Calc::isp_notLow(char a, char b)
{
if ( a == '(' || b == '(') return false;
if ((a == '+' || a == '-') && (b == '*' || b == '/' || b == '%'))
return false;
return true;
}
/**
* main.cpp: 测试程序
*/
#include <iostream>
#include "p_calc.h"
using namespace std;
int main()
{
//p_calc test
string oper;
cout << "please enter your string expression(Ctr-Z to quit): " << endl;
while (getline(cin, oper))
{
Calc calcOper(oper);
if (oper.length() == 0)
cout << "You inputed nothing" << endl;
else if (calcOper.to_postfixExpression())
cout << "Final answer is: " << calcOper.pCalc() << endl << endl;
else
cout << "Bad oper" << endl;
cout << "please enter your string expression(Ctr-Z to quit): " << endl;
}
return 0;
}
- input :
1.2+3.4*(5.6-7.8)/0.9
- output:
1.2 3.4 5.6 7.8 - * 0.9 / +
Final answer is: -7.11111
OK, 以上完 :)