当我们需要计算一个带+ - * / ( ) 的四则运算的时候,我们需要遵循 口诀:先*/后+-乘方最优先 要是有括号就先算括号里面的
计算表达式的方法一(只展示这一过程中的中缀表达式的处理过程)
主要依据的数据结构是栈,需要两个栈,一个用于存储运算分量(operand),另一个用于存储运算符(operators)。
算法的核心思想是:从左向右读取表达式
1.读入当前的字符ch是数字,就压入运算分栈,
2.如果读入的当前字符ch是’(‘,就直接压入运算符栈
3.如果读入的当前字符ch是’+’, ‘-‘, ‘*’, ‘/’, ‘^’进行如下操作
1)将ch与运算符栈栈顶元素进行比较
2)如果ch优先级高,则把ch压入运算符栈,然后再读取字符ch从1.开始从头执行
3)如果ch优先级<=栈顶运算符优先级,则进行”栈顶运算操作”(将运算分量连续弹栈两次,运算符弹栈依次,然后将运算结果存回运算分量栈),然后返回1)执行后续算法
4.如果读入的ch==’)’,则反复执行”栈顶运算操作”,直到遇到的栈顶·元素是’(‘直接弹栈,然后读取字符并且返回1.开始执行,知道表达式计算完毕为止
最核心的思想是,对运算符栈的处理,当运算符栈为空,或当前运算符为’(‘,或者当前运算符的优先级>栈顶运算符的时候直接进行压栈,当前运算符的优先级<=栈顶运算符的时候,弹栈执行相应的运算
#include <stdio.h>
#include <string.h>
#define N 100
char operators[N];
char operand[N];
int operators_top=0,operand_top=0;
void push_operators(const char& op) //用数组模拟堆栈
{
operators[++operators_top]=op;
}
char pop_operators()
{
return operators[operators_top--];
//operators_top--;
}
char top_operators()
{
return operators[operators_top];
}
bool empty_operators()
{
if(operators_top==0)
return true;
else
return false;
}
void push_operand(const char& op)
{
operand[operand_top++]=op;
}
bool isOperator(const char& ch)
{
switch(ch)
{
case '+':
case '-':
case '*':
case '/':
case '^':
case '(':
case ')':
return true;
}
return false;
}
int priority(const char& ch)
{
switch(ch)
{
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
}
return 0;
}
void postfix(char* infix)
{
//char ch;
for(unsigned int i=0;i<strlen(infix);i++)
{
if(isOperator(infix[i]))
{
if( infix[i]==')' )
{
while((top_operators())!='(')
{
push_operand( pop_operators() );
}
pop_operators();
}
else if( empty_operators() || priority(infix[i]) > priority(top_operators()) || infix[i]=='(' )
push_operators(infix[i]);
else if(priority(infix[i]) <= priority(top_operators()))
{
push_operand(pop_operators());
while (!empty_operators())
{
if (priority(infix[i]) <= priority(top_operators()))
{
push_operand(pop_operators());
}
else
break;
}
push_operators(infix[i]);
}
}
else
{
push_operand(infix[i]);
}
}
while (!empty_operators())
{
push_operand(pop_operators());
}
}
int main()
{
memset(operand,0,sizeof(operand));
memset(operators,0,sizeof(operators));
char a[N]="2+3*(3-(5+3-5*4*4+0)/4)";
postfix(&a[0]);
for(int i=0;i<operand_top;i++)
printf("%c",operand[i]);
return 0;
}
计算表达式值的方法2
主要的理论依据是编译原理里面关于四则运算的递归下降的分析方法,要先写出表达式的bnf范式,然后再利用递归下降的分析方法分析bnf范式,利用递归下降的分析方法的时候必须确保消除bnf范式里的左递归
将消除左递归之后的,可以直接将bnf范式利用递归下降的方法写成代码
利用上述思想直接翻译成代码如下:
#include <stdio.h>
#include <stdlib.h>
enum {Num};
int token;
int token_val;
char *src = NULL;
void next() {
while (*src == ' ' || *src == '\t') {
src ++;
}
token = *src++;
if (token >= '0' && token <= '9' ) {
token_val = token - '0';
token = Num;
while (*src >= '0' && *src <= '9') {
token_val = token_val*10 + *src - '0';
src ++;
}
return;
}
}
void match(int tk)
{
next();
}
int expr();
int factor()
{
double value = 0;
if(token=='(')
{
match('(');
value = expr();
match(')');
}else{
value = token_val;
match(Num);
}
return value;
}
int term_tail(int lvalue)
{
if(token=='*'){
match('*');
int value = lvalue * factor();
return term_tail(value);
}else if(token=='/'){
match('/');
int value = lvalue / factor();
return term_tail(value);
}else{
return lvalue;
}
}
int term()
{
int value = factor();
return term_tail(value);
}
int expr_tail(int lvalue)
{
if(token=='+'){
match('+');
int value = lvalue + term();
return expr_tail(value);
}else if(token=='-'){
match('-');
int value = lvalue - term();
return expr_tail(value);
}else{
return lvalue;
}
}
int expr()
{
int value = term();
return expr_tail(value);
}
int main()
{
src="2+3*(3-(5+3-5*4*4)/4)";
next();
printf("%d",expr());
return 0;
}