一、原理探讨
其实如果要理清编译原理之类的东西,第一步就是要搞词法分析,有了词法分析,就可以再做语法分析,我文讨论简单的词法分析的一个小例子—算数表达式,这个是我一个网友问到我的问题,虽然脑子里有个大概的思路,要么使用栈模型,要么使用二叉树模型,但思路不是很清晰,花了一些时间来整理了一下思路并形成了代码。思路如下:
1. 我们要把每个数据拆分开,例:3*2.3+2,即拆成3,*,2.3,+,2
2. 有了单个数据,我们它由中缀转成后缀表达式,3,2.3,*,2,+
3. 有了后缀表达式,我们就可以利用栈特性算出值了。
第一个问题比较好解决,第二个问题,怎么转?有括号怎么办?看似比较麻烦,但实质有规律可寻。规律如下:
1. 符号栈top()优先级大于当前遍历的符号的话,出栈,再入当前当前遍历的符号入栈。
2. 遇’(‘左括号,符号栈保持不变,并添加’(‘入栈。
3. 遇’)’右括号,符号栈一直出栈,直到遇到’(‘左括号。
二、上代码
分析了这如上原理,我们可以写出个试试代码来了。由于没有优化的好,代码可能不是很简洁,但足够分析原理。
#include <iostream>
#include <stack>
#include <algorithm>
#include <vector>
using namespace std;
enum AnalysisType:unsigned char{FLOAT=0x01,OPERATOR=0x02};
struct ItemValue
{
union ValueUnion
{
float fdigit;
char symbol;
};
AnalysisType type;
ValueUnion value;
};
//简单的int加减乘除
int GetPriority(char symbol)
{
switch (symbol)
{
case '+':
case '-':
return 0;
case '*':
case '/':
return 1;
case '(':
case ')':
return 2;
}
return -1;
}
bool IsOperator(char symbol)
{
switch (symbol)
{
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
return true;
}
return false;
}
//转成vector存
void wordsAnalysis(char*pIn, vector<ItemValue>&vec)
{
int nCount = strlen(pIn);
int nIndex = 0;
while (nIndex<nCount)
{
ItemValue item = { FLOAT,0};
//处理操作符
if (IsOperator(pIn[nIndex]))//如果是操作符
{
item.type = OPERATOR;
item.value.symbol = pIn[nIndex];
vec.push_back(item);
}
//处理数字
int nTemp = nIndex;
char nBuffer[20] = {0};//20位
while (isdigit(pIn[nTemp]) || '.'==pIn[nTemp])
{
nBuffer[nTemp - nIndex]=pIn[nTemp];
++nTemp;
}
if (nTemp != nIndex)
{
item.value.fdigit = atof(nBuffer);
vec.push_back(item);
}
//
if (nTemp != nIndex)
nIndex += strlen(nBuffer);
else
++nIndex;
}
}
//中缀转后缀
void midToLast(vector<ItemValue> & vecIn, vector<ItemValue> & vecOut)
{
ItemValue item{ OPERATOR ,0.0f };
stack<char> stack_symbol;
for_each(std::begin(vecIn), std::end(vecIn), [&](ItemValue &it) {
if (FLOAT == it.type )
{
vecOut.push_back(it);
}
else if (OPERATOR == it.type)
{
if (')' == it.value.symbol)
{
while (!stack_symbol.empty())
{
if (stack_symbol.top() == '(')
{
stack_symbol.pop();
return;
}
item.value.symbol = stack_symbol.top();
stack_symbol.pop();
vecOut.push_back(item);
}
}
if (!stack_symbol.empty())
{
if (GetPriority(stack_symbol.top()) - GetPriority(it.value.symbol) >= 0 && stack_symbol.top()!='(')
{
item.value.symbol = stack_symbol.top();
stack_symbol.pop();
vecOut.push_back(item);
}
}
if(')' != it.value.symbol)
stack_symbol.push(it.value.symbol);
}
});
//把栈里的操作符提出来
while (!stack_symbol.empty())
{
item.value.symbol = stack_symbol.top();
stack_symbol.pop();
vecOut.push_back(item);
}
}
//计算
float Calculate(vector<ItemValue>& vec)
{
float fResult=0.0f;
stack<ItemValue> stack_value;
for_each(std::begin(vec), std::end(vec), [&](ItemValue &it) {
if (FLOAT == it.type)
{
stack_value.push(it);
}
else if(OPERATOR == it.type)
{
ItemValue Value1, Value2 ;
Value2=stack_value.top();
stack_value.pop();
Value1=stack_value.top();
stack_value.pop();
switch (it.value.symbol)
{
case '+':
Value1.value.fdigit += Value2.value.fdigit;
break;
case '-':
Value1.value.fdigit -= Value2.value.fdigit;
break;
case '*':
Value1.value.fdigit *= Value2.value.fdigit;
break;
case '/':
Value1.value.fdigit /= Value2.value.fdigit;
break;
}
Value1.type = FLOAT;
stack_value.push(Value1);
}
});
fResult = stack_value.top().value.fdigit;
return fResult;
}
int main()
{
char buffer[64] = {0};
vector<ItemValue> vecIn,vecOut;
cout << "请输入表达式:";
cin >> buffer;
wordsAnalysis(buffer, vecIn);//拆分数据
midToLast(vecIn,vecOut);//转到后缀表达式,vecOut内
cout << "中缀到后缀:";
for_each(std::begin(vecOut), std::end(vecOut), [&](ItemValue &it) {
FLOAT == it.type?
cout << it.value.fdigit << " ":
cout << (char)it.value.symbol << " ";
});
cout <<endl<<"计算结果:" << Calculate(vecOut)<<endl ;
return 0;
}
三、运行成功:
更多文章:http://blog.csdn.net/what951006?viewmode=list
powered by:小乌龟在大乌龟背上~