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

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

表达式求值

题目描述

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

题目解析

本题难度较高,属于高阶题目,需要先转后缀表达式再计算,这里展示一种解法,后续学习了高阶解决方法会更新该题目,下面代码由本人进行一定程度改造所写,基本功能可以实现,如有其他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);
}
相关文章
|
7月前
【栈和队列(1)(逆波兰表达式)】
【栈和队列(1)(逆波兰表达式)】
55 0
数据结构实验之栈与队列二:一般算术表达式转换成后缀式
数据结构实验之栈与队列二:一般算术表达式转换成后缀式
|
存储 算法 编译器
【霍洛维兹数据结构】栈和队列 | 动态循环队列 | 迷宫问题 | 表达式 | 多重栈&多重队列
【霍洛维兹数据结构】栈和队列 | 动态循环队列 | 迷宫问题 | 表达式 | 多重栈&多重队列
105 0
|
2月前
|
存储 算法 Java
数据结构与算法学习八:前缀(波兰)表达式、中缀表达式、后缀(逆波兰)表达式的学习,中缀转后缀的两个方法,逆波兰计算器的实现
前缀(波兰)表达式、中缀表达式和后缀(逆波兰)表达式的基本概念、计算机求值方法,以及如何将中缀表达式转换为后缀表达式,并提供了相应的Java代码实现和测试结果。
137 0
数据结构与算法学习八:前缀(波兰)表达式、中缀表达式、后缀(逆波兰)表达式的学习,中缀转后缀的两个方法,逆波兰计算器的实现
|
2月前
|
算法 Java C语言
【数据结构】后缀(逆波兰)表达式的计算以及中缀转后缀的方法
【数据结构】后缀(逆波兰)表达式的计算以及中缀转后缀的方法
65 0
|
6月前
|
C++
【洛谷 P1739】表达式括号匹配 题解(栈)
该编程题目要求检查给定的包含字母、运算符和括号的表达式是否括号匹配。输入为一行表达式,以`@`结束。如果括号匹配,输出`YES`,否则输出`NO`。样例包括一个匹配和一个不匹配的表达式。解决方案是使用栈,遇到左括号入栈,遇到右括号时判断栈是否为空,栈空则输出`NO`,否则出栈。当读到`@`时,栈空则输出`YES`,否则输出`NO`。提供的AC代码使用C++实现,通过`stack`处理括号匹配。
84 0
|
6月前
|
算法
数据结构和算法学习记录——层序遍历(层次遍历)、二叉树遍历的应用(输出二叉树中的叶节点、求二叉树的高度、二元运算表达式树及其遍历、由两种遍历序列确定二叉树)
数据结构和算法学习记录——层序遍历(层次遍历)、二叉树遍历的应用(输出二叉树中的叶节点、求二叉树的高度、二元运算表达式树及其遍历、由两种遍历序列确定二叉树)
65 0
栈在求值表达式中的应用
栈在求值表达式中的应用
|
算法
数据结构第六章分讲、栈之逆波兰表达式
(ReverseNotation,RPN,或逆波兰记法),也叫(将写在之后)。
138 0
|
1月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
215 9