关于中缀表达式的计算,网上已经有许多代码了,但大多为了学习而专门定义了栈,且不支持识别除数为0等错误。刚好最近需要,所以写了一种尽量精炼的中缀表达式计算方法,在此记录一下。
#include "stdio.h"
#include "stdlib.h"
typedef enum
{
NO_ERROR, // 成功
DIVISION_BY_ZERO, // 除数为0
INVALID_EXPRESSION, // 表达式无效
} CalcErrorType;
// 计算从*buffer开始的表达式
// 利用lastResult和*result参数模拟栈
CalcErrorType getResult(char **buffer, float lastResult, float *result)
{
float num;
char op;
CalcErrorType error;
// 判断表达式结束
if (**buffer == '\0' || **buffer == ')')
{
*result = lastResult;
return NO_ERROR;
}
// 尝试读一个操作符,默认加号(如果当前buffer指向数字)
op = (**buffer == '-' || **buffer == '*' || **buffer == '/') ? *((*buffer)++) : '+';
// 读一个数
if (*((*buffer)++) == '(')
{
if ((error = getResult(buffer, 0, &num)) != NO_ERROR) return error;
(*buffer)++;
}
else
num = strtof(--(*buffer), buffer);
switch (op)
{
case '-':
num = -num;// 把减法当成加一个负数,所以此处不能break
case '+':
if ((error = getResult(buffer, num, &num)) != NO_ERROR) return error;
*result = lastResult + num;
return NO_ERROR;
case '*':
return getResult(buffer, lastResult * num, result);
case '/':
return num == 0 ? DIVISION_BY_ZERO : getResult(buffer, lastResult / num, result);
default:
return INVALID_EXPRESSION;
}
}
int main()
{
char buffer[100], *p1, **p2;
CalcErrorType error;
float result;
while (1)
{
p1 = buffer;
p2 = &p1;
printf("expression: ");
scanf("%s", buffer);
if ((error = getResult(p2, 0, &result)) == NO_ERROR)
printf("result: %f\n", result);
else
printf("error: %d\n", error);
}
return 0;
}
运行效果:
Q.E.D.