中缀算数表达式求值

【题目】中缀表示法(Infix expression),算数表达式求值

1、只考虑 + - * / ( ) 这几个基本运算符,且是二元操作
2、运算数只考虑 0-9,这10个简单的数,方便从string中取出来
3、输入的表达式没有语法错误

【背景知识】

中缀表示法(Infix expression):操作符位于两个操作数中间,算术表达式的常规表示法。只用于二元操作符的情况,而且需要用括号和优先规则排除多义性。(A+B)*C-D/(E+F)

【算符优先法】

输入中缀表达式,直接求值。首先了解四则运算的规则:
(1) 先乘除,后加减
(2) 从左到右
(3) 先括号内,后括号外

下表定义了算符之间的优先级。竖:optr1,横:optr2。
这里写图片描述

规则1:+ - 比* / 的优先权低;
规则2:当optr1=optr2时,令optr1 > optr2;
规则:3:optr1为+ - * / 时的优先级低于 ( 高于 ) ,当optr1为 ( 时,优先级最低,optr1为 ) 时,优先级最高。

#include "stdafx.h"
#include<stdio.h>
#include<malloc.h>
#include <string>

int getpro(char a, char b);
void push(struct ListNode** head, int val);
bool pop(struct ListNode** head, int* val);
bool top(struct ListNode* head, int* val);
void clearnode(struct ListNode** head);

struct ListNode{
    int val;
    struct ListNode* next;
};

double calculate(const char* expr)
{
    double val = 0.0;
    int pre = 0;
    int temp = 0, num1 = 0, num2 = 0;
    struct ListNode* num = NULL;
    struct ListNode* symbol = NULL;
    push(&symbol, '#');

    while (*expr != '\0')
    {
        if (*expr >= '0' && *expr <= '9')
        {
            push(&num, *expr-'0');
            expr++;
        }
        else if (*expr == '(' || *expr == ')' || *expr == '+' || *expr == '-'|| *expr == '*' || *expr == '/' || *expr == '#')
        {
            // 判断获取栈顶是否正确,栈顶值存入pre;
            // pre 优先级高于*expr时,弹出num中两数进行计算,否则操作符继续入栈;
            bool sate = top(symbol, &pre); 

            // 取栈顶失败
            if (!sate)
            {
                printf("Error input string!\n");
                clearnode(&num);
                clearnode(&symbol);
                return val;
            }
            else
            {
                int ret = getpro(pre, *expr);
                // 优先级低,基础入栈
                if (ret < 0)
                {
                    if(ret == -2)
                    {
                        printf("Error input string!\n");
                        clearnode(&num);
                        clearnode(&symbol);
                        return val;
                    }
                    push(&symbol, *expr);
                    expr++;
                }
                // 优先级相同,判断结束 or 清除括号
                else if(ret == 0)
                {
                    if (pre == '(')
                    {
                        pop(&symbol, &temp);
                        ++expr;
                    }
                    else if (pre == '#')
                    {
                        clearnode(&num);
                        clearnode(&symbol);
                        return val;
                    }
                }
                // 优先级高,弹出操作数进行计算
                else
                {
                    pop(&num, &num2);
                    pop(&num, &num1);

                    if (pre == '+') val = num1 + num2;
                    else if (pre == '-') val = num1 - num2;
                    else if (pre == '*') val = num1 * num2;
                    else if (pre == '/') val = num1 / num2;

                    push(&num, val);
                    // 删除栈顶操作符
                    pop(&symbol, &temp); 

                }   
            }
        }       
    }
}

int main()
{
    // 输入表达式以#结束
    char* str = "9*(2+3-1)*(6-8/(3*5-7))#";
    int val = calculate(str);
    return 0;
}

// 入栈
void push(struct ListNode** head, int val)
{
    struct ListNode* cur = *head;
    struct ListNode* pushnode = (struct ListNode*)malloc(sizeof(struct ListNode));
    pushnode->val = val;
    pushnode->next = NULL;

    if (*head == NULL)
    {
        *head = pushnode;
    }
    else
    {
        while(cur->next != NULL)
        {
            cur = cur->next;
        }
        cur->next = pushnode;
    }
}

// 出栈,栈为空则返回false;否则为true,同时将值放入val
bool pop(struct ListNode** head, int* val)
{
    struct ListNode* cur = *head;
    struct ListNode* pre = NULL;

    if (*head == NULL)
    {
        return false;
    }
    else
    {
        while(cur->next != NULL)
        {
            pre = cur;
            cur = cur->next;
        }

        *val = cur->val;
        if (*head == cur)
        {
            *head = NULL;
        }
        else
        {
            pre->next = NULL;
        }
        free(cur);
        return true;
    }
}

// 取得栈顶
bool top(struct ListNode* head, int* val)
{
    struct ListNode* cur = head;

    if (head == NULL)
    {
        return false;
    }
    else
    {
        while(cur->next != NULL)
        {
            cur = cur->next;
        }
        *val = cur->val;
        return true;
    }
}

// 清理栈
void clearnode(struct ListNode** head)
{
    struct ListNode* cur = *head; 
    struct ListNode* temp = NULL; 

    while(cur != NULL)
    {
        temp = cur->next;
        free(cur);
        cur = temp;
    }
    *head = NULL;
}

// 判断优先级
int getpro(char a, char b)
{
    if (a == '+' || a == '-')
    {
        if (b == '+' || b == '-' || b == ')' || b == '#')
            return 1;
        else
            return -1;
    }
    else if (a == '*' || a == '/')
    {
        if (b == '(')
            return -1;
        else
            return 1;
    }
    else if (a == '(')
    {
        if (b == ')')
            return 0;
        else if (b == '#')
            return -2;
        else
            return -1;
    }
    else if (a == ')')
    {
        if(b == '(')
            return -2;
        else
            return 1;
    }
    else if (a == '#')
    {
        if (b == '#')
            return 0;
        else if (b == ')')
            return -2;
        else
            return -1;
    }
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值