现在讲后则表达式生成器。后则表达式能将普通表达式转换成顺序执行的表达式。例如 a*(b+c) 转换成后则表达式就是 bc+a*。意思为先做 b, c 相加,再把结果和 a 相乘。这个项目中后则表达式所用的操作符从操作符表里取出。原表达式中不是操作符的字符即为算子(变量)。此类的接口为:
#if !defined(AFX_BECEXPPARSER_H__EE496CA5_120F_4478_AFE0_85A192E88AD6__INCLUDED_)
#define AFX_BECEXPPARSER_H__EE496CA5_120F_4478_AFE0_85A192E88AD6__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <stack>
class BacExpGenerator
{
public:
BacExpGenerator(char* input, char* szOptrTable, int* prioTable);
virtual ~BacExpGenerator();
public:
std::stack<char>& Parse();
private:
char* input;
std::stack<char> st;
std::stack<char> becExp;
char* szOptrTable;
int* prioTable;
private:
// get index of ch in the szOptrTable.
// on error return -1.
inline int GetIndex(char ch)
{
int i = 0;
while (szOptrTable[i] != 0)
{
if (szOptrTable[i] == ch)
{
return i;
}
i++;
}
return -1;
}
};
#endif // !defined(AFX_BECEXPPARSER_H__EE496CA5_120F_4478_AFE0_85A192E88AD6__INCLUDED_)
此类的核心的压栈出栈算法为:#define AFX_BECEXPPARSER_H__EE496CA5_120F_4478_AFE0_85A192E88AD6__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <stack>
class BacExpGenerator
{
public:
BacExpGenerator(char* input, char* szOptrTable, int* prioTable);
virtual ~BacExpGenerator();
public:
std::stack<char>& Parse();
private:
char* input;
std::stack<char> st;
std::stack<char> becExp;
char* szOptrTable;
int* prioTable;
private:
// get index of ch in the szOptrTable.
// on error return -1.
inline int GetIndex(char ch)
{
int i = 0;
while (szOptrTable[i] != 0)
{
if (szOptrTable[i] == ch)
{
return i;
}
i++;
}
return -1;
}
};
#endif // !defined(AFX_BECEXPPARSER_H__EE496CA5_120F_4478_AFE0_85A192E88AD6__INCLUDED_)
stack<char>& BacExpGenerator::Parse()
{
// clear stacks.
while (!st.empty())
{
st.pop();
}
while (!becExp.empty())
{
becExp.pop();
}
// begin //
//////////////////////
for (int i = 0; input[i] != 0; i++)
{
char ch = input[i];
int index = GetIndex(ch);
// if ch is a operand
if (index == -1)
{
st.push(ch);
continue;
}
// if ch is a operator
if (st.empty() || ch == '(')
{
st.push(ch);
}
else
{
char lastItem = st.top();
int indexOfLastItem = GetIndex(lastItem);
while (prioTable[indexOfLastItem] >= prioTable[index] || ch == ')')
{
st.pop();
if (lastItem == '(') break;
becExp.push(lastItem);
if (st.empty()) break;
lastItem = st.top();
indexOfLastItem = GetIndex(lastItem);
}
if (ch != ')') st.push(ch);
}
}
while (!st.empty())
{
becExp.push(st.top());
st.pop();
}
return becExp;
}
此算法的一个替代就是先生成一个树,然后用后序遍历也一样可以得出后则表达式。不过,我认为这个算法还是比较好的。因为它一次性解决问题。
{
// clear stacks.
while (!st.empty())
{
st.pop();
}
while (!becExp.empty())
{
becExp.pop();
}
// begin //
//////////////////////
for (int i = 0; input[i] != 0; i++)
{
char ch = input[i];
int index = GetIndex(ch);
// if ch is a operand

if (index == -1)
{
st.push(ch);
continue;
}
// if ch is a operator

if (st.empty() || ch == '(')
{
st.push(ch);
}
else
{
char lastItem = st.top();
int indexOfLastItem = GetIndex(lastItem);
while (prioTable[indexOfLastItem] >= prioTable[index] || ch == ')')
{
st.pop();
if (lastItem == '(') break;
becExp.push(lastItem);
if (st.empty()) break;
lastItem = st.top();
indexOfLastItem = GetIndex(lastItem);
}
if (ch != ')') st.push(ch);
}
}
while (!st.empty())
{
becExp.push(st.top());
st.pop();
}
return becExp;
}