本文实现整数的四则混合混算。比如:输入(5+8*4+7)*9-3*(13+2*6),返回计算结果为321。
思路:正向扫描表达式,使用两个栈分别存储整数和符号,有括号的先计算括号中的值。遇到乘除法先计算。经过以上计算后得到最后的式子为只有加减法的无括号式子。再计算最后结果。
流程描述:
1. 扫描字符t。
2. 若为’\0’,跳到4;若为’*/+)’,入符号栈;若为’-‘,转化为(-1)*,分别入数字栈和符号栈;若为数字’0-9’,向前找到不是’0-9’的符号,转化为整数,入数字栈;若为’)’,符号栈依次出栈计算数字栈顶两元素后入数字栈,直到遇到’(‘出栈,跳到3。
3. t++,跳回1。
4. 符号栈依次出栈计算数字栈数据,直到符号栈为空。跳到5。
5. 数字栈栈顶元素为结果。结束。
输入:符合四则运算的整数数字运算表达式,可以有括号,负数。表达式合法性不在此程序验证范围之内,如果需要验证请在外围加验证函数。
输出:运算表达式结果。
限制:表达式使用的数字栈和符号栈的大小会限制计算的表达式范围;大数加减乘除不在此程序处理;
使用例子:
char expession[] = "(5+8*4+7)*9-3*(13+002*6)";
int ret = calculate_expression(expession);
程序代码:说明,如果想更清楚的了解运算过程和栈的变化,请自行加上栈数据打印函数。
程序代码:说明,如果想更清楚的了解运算过程和栈的变化,请自行加上栈数据打印函数。
#define ERROR_VALUE 0xffffffff
#define MAX_STACK 0x10
//数字栈
int int_stack[MAX_STACK];
int is_top=-1;
//数字入栈
bool is_push(int i)
{
if (is_top<(MAX_STACK-1))
{
int_stack[++is_top]=i;
return true;
}
return false;
};
//数字出栈
int is_pop()
{
if (is_top>=0)
{
int p = int_stack[is_top];
is_top--;
return p;
}
return ERROR_VALUE;
};
//符号栈
char char_stack[MAX_STACK];
int cs_top = -1;
//符号入栈
bool cs_push(char ch)
{
if (cs_top<(MAX_STACK-1))
{
char_stack[++cs_top] = ch;
return true;
}
return false;
};
//符号出栈
char cs_pop()
{
if (cs_top>=0)
{
char p = char_stack[cs_top];
cs_top--;
return p;
}
return -1;
};
//二元表达式计算
int calculate(int left,int right,char exp)
{
if (exp == '*')
{
return right*left;
}
if (exp == '/')
{
return left/right;
}
if (exp == '+')
{
return left+right;
}
if (exp == '-')
{
return left -right;
}
return ERROR_VALUE;
};
//四则混合运算式计算
int calculate_expression(char *expession)
{
char *t = expession;
char m;
int n;
while(*t!='\0')
{
switch (*t)
{
case '+':
case '*':
case '/':
case '(':
cs_push(*t);
break;
case '-':
//使用"+(-1)*"来代替"-",可以避免*(-3),这样的负数带来的影响
cs_push('+');
cs_push('*');
is_push(-1);
break;
case ')':
//数据栈顶两个元素用运算符栈顶的元素计算后入数据栈,要直找到'('的位置才结束计算
m = cs_pop();
do
{
int r = is_pop();
int l = is_pop();
n = calculate(l,r,m);
is_push(n);
m = cs_pop();
} while (m!='(');
//把括号左边的最近的乘除法先计算出来,注意,加减不能算,因为括号后面还有可能有乘除法。
m = cs_pop();
if ( m=='*' || m == '/')
{
int r = is_pop();
int l = is_pop();
n = calculate(l,r,m);
is_push(n);
}
else if (m>0)
{
cs_push(m);
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
//如果有连续-9数字则组合为一个数字进栈
char str[8];
int i = 0;
while( *t>='0' && *t <= '9')
{
str[i] = *t;
i++;
t++;
}
str[i] = '\0';
t--;
n = atoi(str);
is_push(n);
//把数值左边的最近的乘除法先计算出来,注意,加减不能算,因为数值后面还有可能有乘除法。
m = cs_pop();
if ( m=='*' || m == '/')
{
int r = is_pop();
int l = is_pop();
n = calculate(l,r,m);
is_push(n);
}
else if (m>0)
{
cs_push(m);
}
}
break;
default:
printf("expression input error!");
break;
}
t++;
}
//上面已经做完所有乘法和括号的运算,若还有加减法没做完,把剩下的工作做完
while ((m = cs_pop())>0)
{
int r = is_pop();
int l = is_pop();
n = calculate(l,r,m);
is_push(n);
}
printf("the result is %d",n);
return n;
}