例如我们做到一个计算器的时候我们会遇到1+9+6/8类似这种,那么我们就可以用把这个式子变成后缀表达式然后再来计算。
struct//设定运算符的优先级
{
char ch;//运算符
int pri;//优先级
}lpri[] = { { '=', 0 }, { '(', 1 }, { '*', 5 }, { '/', 5 }, { '+', 3 }, { '-', 3 }, { ')', 6 } },
rpri[] = { { '=', 0 }, { '(', 6 }, { '*', 4 }, { '/', 4 }, { '+', 2 }, { '-', 2 }, { ')', 1 } };
int leftpri(char op)//左边运算符的优先级
{
int i;
for (i = 0; i<7; i++)
if (lpri[i].ch == op)return lpri[i].pri;
}
int rightpri(char op)//右运算符的优先级
{
int i;
for (i = 0; i<7; i++)
if (rpri[i].ch == op)
return rpri[i].pri;
}
bool InOp(char ch)//判断ch是不是运算符
{
if (ch == '(' || ch == ')' || ch == '+' || ch == '-' || ch == '*' || ch == '/')
return true;
else
return false;
}
int Precede(char op1, char op2)//op1和op2运算符的优先级情况
{
if (leftpri(op1) == rightpri(op2))
return 0;
if (leftpri(op1)<rightpri(op2))
return -1;
else
return 1;
}
void trans(char *exp, char postexp[])//将一般的表达式转成后缀表达式
{
struct //存放运算符
{
char data[1000];
int top;//栈指针
}op;
int i = 0;
op.top = -1;
op.top++;
op.data[op.top] = '=';
while (*exp != '\0')//exp表达式未扫描完时循环
{
if (!InOp(*exp))//若是数字的时候
{
while (*exp >= '0'&&*exp <= '9')//判断为数字
{
if (*(exp - 2) == '(' && (*(exp - 1) == '+' || *(exp - 1) == '-' || *(exp - 1) == '*' || *(exp - 1) == '/'))//是是负数的符号而不是减号
{
postexp[i++] = '&';//这个是为了处理负数的情况,如果是负数则会出现&和数字 例如&5
int a = i + 1;
postexp[a++] = *exp;
}
postexp[i++] = *exp;
exp++;//存放表达式
}
postexp[i++] = '#';//用一个#号隔开
}
else//如果是运算符的情况
{
if ((*exp == '+' || *exp == '-' || *exp == '*' || *exp == '/') && *(exp - 1) == '(' && (*(exp + 1) >= '0'&&*(exp + 1) <= '9'))//除掉是负数的-号
{
exp++;
continue;
}
else
{
switch (Precede(op.data[op.top], *exp))
{
case -1://栈顶运算符的优先级低
op.top++;
op.data[op.top] = *exp;
exp++;
break;
case 0://只有括号满足这种情况
op.top--;
exp++;
break;
case 1://退栈并输入到postexp数组中
postexp[i++] = op.data[op.top];
op.top--;
break;
}
}
}
}
while (op.data[op.top] != '=')//此时已经扫描好了,退栈到'='结束
{
postexp[i++] = op.data[op.top];
op.top--;
}
postexp[i] = '\0';//添加一个结束标志
}
float compvalue(char *postexp)//通过后缀表达式开始计算值
{
struct
{
float data[1000];//存放数字的数组
int top;
}st;
float d, a, b, c;
st.top = -1;
while (*postexp != '\0')//当postexp字符串为扫描完时
{
switch (*postexp)
{
case '+'://判断是'+’的时候
a = st.data[st.top];
st.top--;
b = st.data[st.top];
st.top--;
c = a + b;
st.top++;
st.data[st.top] = c;//这就是计算两个数字相加的时候a,b退栈计算c然后进栈
break;
case '-':
a = st.data[st.top];
st.top--;
b = st.data[st.top];
st.top--;
c = b - a;
st.top++;
st.data[st.top] = c;
break;
case '*':
a = st.data[st.top];
st.top--;
b = st.data[st.top];
st.top--;
c = b*a;
st.top++;
st.data[st.top] = c;
break;
case '/':
a = st.data[st.top];
st.top--;
b = st.data[st.top];
st.top--;
if (a != 0)
{
c = b / a;
st.top++;
st.data[st.top] = c;
}
else
{
printf("error(分母为0)\n");
exit(0);
}
break;
default:
d = 0;
int find = 0;
while (*postexp >= '0'&&*postexp <= '9'&&*postexp != '&')
{
if (*(postexp - 1) == '&')
{
find = 1;
}
else
{
find = -1;
}
d = 10 * d + *postexp - '0';
postexp++;
}
if (find == 1)
{
st.top++;
st.data[st.top] = -d;
}
else if (find == -1)
{
st.top++;
st.data[st.top] = d;
}
break;
}
postexp++;
}
return(st.data[st.top]);//最后指针指的位置就是值
}
这个是c++版本的 ,现在正在把这个做成java包以后专用使用