关于中缀表达式的计算,网上已经有许多代码了,但大多为了学习而专门定义了栈,且不支持识别除数为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;
}

  运行效果:
捕获.PNG

Q.E.D.