由中缀式转换成后缀式,同样使用栈,并运用一些规则来完成。规则介绍如下:
- 当读到的是操作数,立即输出。
- 当读到的是运算符,则先从栈中弹出优先级高于自己的运算符(不包含括号),自己入栈。
- 读到左括号入栈,读到右括号则将栈中元素出栈并输出,直到遇见左括号(括号都不输出)。
- 输入为空后,将栈元素弹出并输出直到栈空。
注意,最后生成的后缀表达式是考虑了运算符优先级的,再配合逆波兰的无优先级概念这一性质,就能够编写出一个带运算符优先级和括号的简易计算器了。
下面是完整的计算器代码,整型四则运算,可加括号。写了一个下午,幸苦呀~
#include <iostream>
#include <vector>
#include <stack>
#include <ctype.h>
#include <cstdlib>
#include <sstream>
using namespace std;
bool IsDigit(string str)
{
for(int i = 0; i < str.size(); i++)
if ((str.at(i) > '9') || (str.at(i) < '0'))
return false;
return true;
}
int main()
{
stack<string> s;
vector<string> postfix; // 存放后缀表达式,作为求运算结果的输入
string input;
while (cin >> input)
{
if (IsDigit(input))
//cout << input << ' ';
postfix.push_back(input);
else if (input == "(")
s.push(input);
else if (input == "+" || input == "-")
{
while ((!s.empty()) && (s.top() != "("))
{ // 弹出优先级大于等于“+”“-”的运算符直到遇到“(”
//cout << s.top() << ' ';
postfix.push_back(s.top());
s.pop();
}
s.push(input);
}
else if (input == "*" || input == "/")
{
// 在不知道栈是否为空时,不能top()
while ((!s.empty()) && (s.top() != "(") &&
(s.top() != "+") && (s.top() != "-"))
{ // 弹出运算符“*”“/”直到遇到“(”
//cout << s.top() << ' ';
postfix.push_back(s.top());
s.pop();
}
s.push(input);
}
else if (input == ")")
{
while ((!s.empty()) && (s.top() != "("))
{ // 弹出直到遇到“(”
//cout << s.top() << ' ';
postfix.push_back(s.top());
s.pop();
}
s.pop(); // 弹出“(”
}
else
{ // 遇到非法字符
cout << "Input illegal";
return -1;
}
}
while (!s.empty())
{
//cout << s.top() << ' ';
postfix.push_back(s.top());
s.pop();
}
vector<string>::iterator iter = postfix.begin();
for ( ; iter != postfix.end(); iter++)
cout << *iter;
#if 1
cout << endl;
iter = postfix.begin();
while (iter != postfix.end())
{
input = *iter;
if (IsDigit(input))
s.push(input);
else if ((input == "+") || (input == "-") || (input == "*") || (input == "/"))
{
int lhs = atoi((s.top()).c_str());
s.pop();
int rhs = atoi((s.top()).c_str());
s.pop();
stringstream ss;
string midval;
switch (*input.c_str())
{
case '+' :
ss << (lhs+rhs);
ss >> midval;
s.push(midval);
break;
case '-' :
ss << (lhs-rhs);
ss >> midval;
s.push(midval);
break;
case '*' :
ss << (lhs*rhs);
ss >> midval;
s.push(midval);
break;
case '/' :
ss << (rhs/lhs); // 注意除法的操作数有顺序限制
ss >> midval;
s.push(midval);
break;
}
}
iter++;
}
cout << s.top();
#endif
return 0;
}
参考:
《数据结构于算法分析》 P54。