数据结构---表达式求值

简介: 数据结构---表达式求值

表达式求值

题目描述

从键盘输入一个算术表达式并输出它的结果,算术表达式可包含加、减、乘、除、十进制整数和小括号,利用栈实现。

题目解析

本题难度较高,属于高阶题目,需要先转后缀表达式再计算,这里展示一种解法,后续学习了高阶解决方法会更新该题目,下面代码由本人进行一定程度改造所写,基本功能可以实现,如有其他bug自行解决

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define N 30

typedef struct my_stack
{
   
    int a[N];
    int top;
}ST;

int isempty(ST* T)
{
   
    if (T->top < 0)
        return 1;
    else
        return 0;
}

int isfull(ST* T)
{
   
    if (T->top == N - 1)
        return 1;
    else
        return 0;
}

int gettop(ST* T)
{
   
    return T->a[T->top];
}

int pop(ST* T)
{
   
    int x;
    if (T->top < 0)
    {
   
        printf("Zhan is empty,can not pop!\n");
        exit(0);
    }
    else
    {
   
        x = T->a[T->top];
        (T->top)--;
        return x;
    }
}

void push(ST* T, int s)
{
   
    if (T->top == N - 1)
    {
   
        printf("Zhan is full,can not push,you can modify N and then you can push again.\n");
        exit(0);
    }
    else
    {
   
        (T->top)++;
        T->a[T->top] = s;
    }
}

void transfer(char* in, char* post)
{
   
    ST T;
    int i, j, flag = 0;
    int count;
    int right = 0, left = 0;
    T.top = -1;
    for (i = 0, j = 0; in[i] != '\0'; i++)
    {
   
        switch (in[i])
        {
   
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            for (count = 0; (in[i] <= '9' && in[i] >= '0') || in[i] == '.'; i++, j++)
            {
   
                post[j] = in[i];
                if (in[i] == '.')
                    count++;
            }
            i--;
            if (count > 1)
            {
   
                printf("数中有两个小数点\n");
                exit(0);
            }
            post[j] = ' ';
            j++;
            flag = 1;
            break;
        case '(':
            if (flag)
            {
   
                printf("数字后直接跟括号\n");
                exit(0);
            }
            push(&T, in[i]);
            left++;
            break;
        case ')':
            right++;
            while (gettop(&T) != '(')
            {
   
                post[j] = pop(&T);
                j++;
            }
            pop(&T);
            break;
        case '+':

        case '-':
            if (!flag && i != 0)
            {
   
                printf("有连续两个运算符之间没有数字\n");
                exit(0);
            }
            while (!isempty(&T) && gettop(&T) != '(')
            {
   
                post[j] = pop(&T);
                j++;
            }
            push(&T, in[i]);
            flag = 0;
            break;
        case '*':

        case '/':
            if (!flag)
            {
   
                printf("有连续两个运算符之间没有数字\n");
                exit(0);
            }
            while (!isempty(&T) && (gettop(&T) == '/' || gettop(&T) == '*'))
            {
   
                post[j] = pop(&T);
                j++;
            }
            push(&T, in[i]);
            flag = 0;
            break;
        default:
            printf("输入非法字符,无法试别\n");
            exit(0);
        }
    }
    if (left != right)
    {
   
        printf("左右括号不匹配\n");
        exit(0);
    }
    while (!isempty(&T))
    {
   
        post[j] = pop(&T);
        j++;
    }
    post[j] = '\0';
}

float Calculate_zhong(char* post)
{
   
    int i, j, top = -1, flag;
    int len;
    float temp, aa[N]={
   0};
    char ch[N];
    for (i = 0; post[i] != '\0'; i++)
    {
   
        if (post[i] >= '0' && post[i] <= '9')
        {
   
            flag = 0;
            j = 0;
            while (post[i] != ' ')
            {
   
                if (post[i] == '.')
                {
   
                    flag = 1;
                }
                ch[j] = post[i];
                i++;
                j++;
            }
            ch[j] = '\0';
            if (flag)
            {
   
                for (j = 0; ch[j] != '.'; j++);
                len = j - 1;
                for (j = 0, temp = 0.; ch[j] != '.'; j++)
                {
   
                    temp += (ch[j] - '0') * (float)pow(10, len - j);
                }
                for (j++, len++; ch[j] != '\0'; j++)
                {
   
                    temp += (ch[j] - '0') * (float)pow(10, len - j);
                }
            }
            else
            {
   
                for (j = 0; ch[j] != '\0'; j++);
                len = j - 1;
                for (j = 0, temp = 0.; ch[j] != '\0'; j++)
                {
   
                    temp += (ch[j] - '0') * (float)pow(10, len - j);
                }
            }
            top++;
            aa[top] = temp;
        }
        else
        {
   
            switch (post[i])
            {
   
            case'+':
                temp = aa[top];
                top--;
                temp += aa[top];
                aa[top] = temp;
                break;
            case'-':
                temp = aa[top];
                top--;
                temp = aa[top] - temp;
                aa[top] = temp;
                break;
            case'*':
                temp = aa[top];
                top--;
                temp = temp * aa[top];
                aa[top] = temp;
                break;
            case'/':
                temp = aa[top];
                top--;
                temp = aa[top] / temp;
                aa[top] = temp;
            }
        }
    }
    return aa[top];
}


int main()
{
   
    char zhong[N], hou[N];
    float answer;
    printf("需要计算的中缀表达式为:");
    scanf("%s", zhong);
    transfer(zhong, hou);
    answer = Calculate_zhong(hou);
    printf("%.2f\n", answer);
}
相关文章
|
3月前
【栈和队列(1)(逆波兰表达式)】
【栈和队列(1)(逆波兰表达式)】
30 0
|
9月前
|
存储 算法 编译器
【霍洛维兹数据结构】栈和队列 | 动态循环队列 | 迷宫问题 | 表达式 | 多重栈&多重队列
【霍洛维兹数据结构】栈和队列 | 动态循环队列 | 迷宫问题 | 表达式 | 多重栈&多重队列
63 0
|
2月前
|
C++
【洛谷 P1739】表达式括号匹配 题解(栈)
该编程题目要求检查给定的包含字母、运算符和括号的表达式是否括号匹配。输入为一行表达式,以`@`结束。如果括号匹配,输出`YES`,否则输出`NO`。样例包括一个匹配和一个不匹配的表达式。解决方案是使用栈,遇到左括号入栈,遇到右括号时判断栈是否为空,栈空则输出`NO`,否则出栈。当读到`@`时,栈空则输出`YES`,否则输出`NO`。提供的AC代码使用C++实现,通过`stack`处理括号匹配。
29 0
ACM刷题之路(十一)堆、栈、队列实现表达式转换
ACM刷题之路(十一)堆、栈、队列实现表达式转换
|
10月前
栈在求值表达式中的应用
栈在求值表达式中的应用
|
存储 算法 C语言
数据结构 | 栈的中缀表达式求值
数据结构 | 栈的中缀表达式求值
|
算法 程序员
Qz学算法-数据结构篇(表达式、递归)
数据结构的前缀、中缀、后缀表达式-&gt;(逆波兰表达式)和递归
133 0
【LC】有效的括号,逆波兰表达式,栈的压入 弹出序列,最小栈
【LC】有效的括号,逆波兰表达式,栈的压入 弹出序列,最小栈
124 0
【LC】有效的括号,逆波兰表达式,栈的压入 弹出序列,最小栈
|
存储 算法 C语言
C语言数据结构 | 堆栈顺序、链式存储及表达式求值
从计算机对表达式求值引入算数表达式在求值时若无优先级,那么从左到右运算就很容易,但算术表达式由两类对象构成一个是一个是+-*/······不同的运算符号优先级也不一样此时运算就比较困难 ,无法判断运算符后一个运算数是否参与这次运算。
C语言数据结构 | 堆栈顺序、链式存储及表达式求值
|
6天前
|
算法 C语言 C++
【practise】栈的压入和弹出序列
【practise】栈的压入和弹出序列