数据结构——表达式求值(中序)

表达式求值(中序)

实验二 基于栈的中缀算术表达式求值
【实验目的】
1.掌握栈的基本操作算法的实现,包括栈初始化、进栈、出栈、取栈顶元素等。
2.掌握利用栈实现中缀表达式求值的算法。
【实验内容】
问题描述
输入一个中缀算术表达式,求解表达式的值。运算符包括“+”、“-”、“”、“/”、“(”、“)”、“=”,参加运算的数为 double类型且为正数。(要求:直接使用中缀算术表达式进行计算,不能转换为后缀或前缀表达式再进行计算,只考虑二元运算即可。)
输入要求
多组数据,每组数据一行,对应一个算术表达式,每个表达式均以“=”结尾。当表达式只有一个“=”时,输入结束。参加运算的数为 double类型。
输出要求
对于每组数据输出1行,为表达式的运算结果。输出保留两位小数。
输入样例
2+2=
20
(4.5-3)=
输出样例
4.00
30.00
【实验提示】
此实验内容即为教材(P53)算法3.4的扩展内容,算法3.4只考虑个位数的运算,不具备拼数功能。拼数功能可以手工编写,也可以借助C语言的库函数atof()函数来完成,其功能是将字符串转换为双精度浮点数( double)。

解决问题的核心思路:

为实现算符优先算法,可以使用两个工作栈:
1.一个称为OPTR,用于寄存运算符
2.另一个称做OPND,用于寄存操作数或运算结果
算法的基本思想:
(1):首先置操作数栈为空栈,表达式的起始符“=”为运算符栈的栈底元素;
(2):依次读入表达式中的每一个字符:
若是操作数则进OPND栈,若是运算符则和OPND栈的栈顶运算符比较
若栈顶运算符<运算符c:运算符c进栈OPND
若栈顶运算符=运算符c:(此时栈顶运算符为“(”,运算符c为”)”)
若栈顶运算符>运算符c:将栈顶运算符出栈,进行运算
(3)直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“=”)。

完成这个问题需要的知识前提:栈

知识前提:栈的基本运算
顺序栈

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;typedef int Status;
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0// ------栈的顺序存储结构表示----------
#define STACK_INIT_SIZE 100 	// 存储空间初始分配量
#define STACK_INCREMENT 10 	// 存储空间分配增量
typedef int  ElemType;
typedef struct {ElemType *base; 	// 栈底指针ElemType *top; 	// 栈顶指针int stacksize; 	// 栈空间大小
} SqStack;void InitStack(SqStack &S)
{// 构造一个空栈Sif(!(S.base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType))))exit(OVERFLOW);     // 存储分配失败S.top = S.base;S.stacksize = STACK_INIT_SIZE;
}void DestroyStack(SqStack &S)
{// 销毁栈S,S不再存在free(S.base);S.base = NULL;S.top = NULL;S.stacksize = 0;
}void Push(SqStack &S, ElemType e)
{if(S.top - S.base >= S.stacksize) { // 栈满,追加存储空间S.base = (ElemType *)realloc(S.base, (S.stacksize + STACK_INCREMENT) * sizeof(ElemType));if(!S.base)exit(OVERFLOW);           // 存储分配失败S.top = S.base + S.stacksize;S.stacksize += STACK_INCREMENT;}*(S.top)++ = e;
}Status Pop(SqStack &S, ElemType &e)
{// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;// 否则返回ERRORif(S.top == S.base)return ERROR;e = *--S.top;return OK;
}Status GetTop(SqStack S, ElemType &e)
{// 若栈不空,则用e返回S的栈顶元素,并返回OK;// 否则返回ERRORif(S.top > S.base) {e = *(S.top - 1);return OK;}elsereturn ERROR;
}Status StackEmpty(SqStack S)
{// 若栈S为空栈,则返回TRUE,否则返回FALSEif(S.top == S.base)return TRUE;elsereturn FALSE;
}int main ()
{int n=1;ElemType e,q,temp;int a;SqStack P;InitStack(P);printf("入栈输入:1 ,出栈输入:2 ,得到栈顶元素输入:3 , 判断栈是否为空:4 ,销毁栈:5  \n");while(n){printf("输入操作:"); scanf("%d",&a); switch(a){case 1: printf("入栈操作,输入要入栈的元素:"); scanf("%d",&e);Push(P, e);break;case 2: printf("出栈操作\n"); Pop(P, q);printf("当前出栈的元素的值为:%d\n",q);break;case 3: GetTop(P, temp);printf("输出栈顶元素为 %d \n",temp);break;case 4: if(StackEmpty(P)) printf("当前栈为空\n");else printf("当前栈不空\n"); break;case 5: printf("---正在销毁栈---\n");DestroyStack(P);break;}}} 

判断运算符优先级函数
//思路:
1.先实用二维数组存储运算符的优先级
2.使用switch语句对传入的参数进行优先级比较

//根据教科书表3.1,判断两符号的优先关系
char Precede(char t1, char t2){  int i,j;  char pre[7][7]={           //运算符之间的优先级制作成一张表格  {'>','>','<','<','<','>','>'},  {'>','>','<','<','<','>','>'},  {'>','>','>','>','<','>','>'},  {'>','>','>','>','<','>','>'},  {'<','<','<','<','<','=','0'},  {'>','>','>','>','0','>','>'},  {'<','<','<','<','<','0','='}};  switch(t1){  case '+': i=0; break;  case '-': i=1; break;  case '*': i=2; break;  case '/': i=3; break;  case '(': i=4; break;  case ')': i=5; break;  case '=': i=6; break;  }  switch(t2){  case '+': j=0; break;  case '-': j=1; break;  case '*': j=2; break;  case '/': j=3; break;  case '(': j=4; break;  case ')': j=5; break;  case '=': j=6; break;  }  return pre[i][j];  
}  

判断字符c是否是运算符
//思路:
1.使用switch语句对c进行判断

//判断c是否为运算符
Status In(OperandType c)
{switch(c){case '+':case '-':case '*':case '/':case '(':case ')':case '=':return TRUE;default:return FALSE;}}

二元运算函数如:+ - * /


//二元运算(a theta b)
ElemType Operate(ElemType a, OperandType theta, ElemType b)
{ElemType c;switch(theta){case '+':c = a + b;break;case '-':c = a - b;break;case '*':c = a * b;break;case '/':c = a / b;break;}return c;
}

表达式求值的全部代码(可以直接运行使用)


#include <stdio.h>
#include <stdlib.h>//函数atof()将字符串转化为一个浮点数值,atoi()将一个字符串转化为一个整数数值 
//atol()将一个字符串转化为一个长整数
//malloc()函数 
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1  
#define OVERFLOW -2
#define STACK_INIT_SIZE 100   //存储空间初始分配量
#define STACKINCREMENT 10   //存储空间分配增量typedef char SElemType;
typedef double ElemType;
typedef char OperandType;   //表达式求值的运算类型
typedef int Status;typedef struct
{SElemType *base;SElemType *top;int stacksize;
}SqStack;//构造一个空栈
Status InitStack(SqStack *S)
{S->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));if(!S->base){printf("内存分配失败!\n");exit(OVERFLOW);}S->top = S->base;S->stacksize = STACK_INIT_SIZE;return OK;
}//若栈不为空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
Status GetTop(SqStack *S, SElemType *e)
{if(S->top == S->base)return ERROR;*e = *(S->top - 1);return OK;
}//插入元素e为新的栈顶元素
Status Push(SqStack *S, SElemType e)
{if(S->top - S->base >= STACK_INIT_SIZE)   //栈满, 追加存储空间{S->base = (SElemType *)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(SElemType));if(!S->base){printf("内存分配失败!\n");exit(OVERFLOW);}S->top = S->base + S->stacksize;S->stacksize += STACKINCREMENT;}*S->top++ = e;return OK;
}//若栈不为空,则删除S的栈顶元素,用e返回其值,并返回Ok;否则返回ERROR
Status Pop(SqStack *S, SElemType *e)
{if(S->top == S->base)return ERROR;*e =  *--S->top;return OK;
}
//销毁栈S,使其不复存在
Status StackDestroy(SqStack *S)
{free(S->base);S->base = NULL;S->top = NULL;S->stacksize = 0;return OK;
}//清空栈S,保留栈底指针
void ClearStack(SqStack *S)
{S->top = S->base;
}typedef struct
{ElemType *base;ElemType *top;int stacksize;
}SqStack_double;//构造一个空栈
Status InitStack(SqStack_double *S)
{S->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));if(!S->base){printf("内存分配失败!\n");exit(OVERFLOW);}S->top = S->base;S->stacksize = STACK_INIT_SIZE;return OK;
}//若栈不为空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
Status GetTop(SqStack_double *S, ElemType *e)
{if(S->top == S->base)return ERROR;*e = *(S->top - 1);return OK;
}//插入元素e为新的栈顶元素
Status Push(SqStack_double *S, ElemType e)
{if(S->top - S->base >= STACK_INIT_SIZE)   //栈满, 追加存储空间{S->base = (ElemType *)realloc(S->base, (S->stacksize + STACKINCREMENT) * sizeof(ElemType));if(!S->base){printf("内存分配失败!\n");exit(OVERFLOW);}S->top = S->base + S->stacksize;S->stacksize += STACKINCREMENT;}*S->top++ = e;return OK;
}//若栈不为空,则删除S的栈顶元素,用e返回其值,并返回Ok;否则返回ERROR
Status Pop(SqStack_double *S, ElemType *e)
{if(S->top == S->base)return ERROR;*e =  *--S->top;return OK;
}
//销毁栈S,使其不复存在
Status StackDestroy(SqStack_double *S)
{free(S->base);S->base = NULL;S->top = NULL;S->stacksize = 0;return OK;
}//清空栈S,保留栈底指针
void ClearStack(SqStack_double *S)
{S->top = S->base;
}//根据教科书表3.1,判断两符号的优先关系
char Precede(char t1, char t2){  int i,j;  char pre[7][7]={           //运算符之间的优先级制作成一张表格  {'>','>','<','<','<','>','>'},  {'>','>','<','<','<','>','>'},  {'>','>','>','>','<','>','>'},  {'>','>','>','>','<','>','>'},  {'<','<','<','<','<','=','0'},  {'>','>','>','>','0','>','>'},  {'<','<','<','<','<','0','='}};  switch(t1){  case '+': i=0; break;  case '-': i=1; break;  case '*': i=2; break;  case '/': i=3; break;  case '(': i=4; break;  case ')': i=5; break;  case '=': i=6; break;  }  switch(t2){  case '+': j=0; break;  case '-': j=1; break;  case '*': j=2; break;  case '/': j=3; break;  case '(': j=4; break;  case ')': j=5; break;  case '=': j=6; break;  }  return pre[i][j];  
}  
//判断c是否为运算符
Status In(OperandType c)
{switch(c){case '+':case '-':case '*':case '/':case '(':case ')':case '=':return TRUE;default:return FALSE;}}//二元运算(a theta b)
ElemType Operate(ElemType a, OperandType theta, ElemType b)
{ElemType c;switch(theta){case '+':c = a + b;break;case '-':c = a - b;break;case '*':c = a * b;break;case '/':c = a / b;break;}return c;
}//算术表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合
ElemType EvaluateExpression()
{SqStack OPTR;//运算符栈 SqStack_double OPND;//操作数栈 ElemType b,a,result;//double 类型的 OperandType  x,theta;//char类型的 char c;   //存放有键盘输入的字符串char z[10];InitStack(&OPTR);   //初始化运算符栈Push(&OPTR, '=');   //=是表达式结束符InitStack(&OPND);   //初始化运算数栈c = getchar();GetTop(&OPTR, &x);while(c != '=' || x != '='){if(In(c))   //是7种运算符之一{switch(Precede(x, c)){case '<':   //当前已经压栈一个运算符(x)比后一个运算符(c)低时,就将c压栈Push(&OPTR, c);c = getchar();break;case '='://消除小括号 Pop(&OPTR, &x);   //脱括号并接收下一字符c = getchar();break;case '>'://将部分表达式求值(两个操作数) Pop(&OPTR, &theta);   //退栈并将运算结果压入OPND中Pop(&OPND, &b);Pop(&OPND, &a);Push(&OPND, Operate(a, theta, b));break;}}else if(c >= '0' && c <= '9'||c=='.'){		ElemType sum=0;int i=0;//将字符串中的数字转化为数组存储 while(c >= '0' && c <= '9'||c=='.') {z[i]=c;i++;c = getchar();}z[i]='\0';sum= atof(z);Push(&OPND, sum);}else   //c为非法字符{printf("输入表达式有误\n");exit(1);}GetTop(&OPTR, &x);//为了修改switch(Precede(x, c))里面的x; }GetTop(&OPND, &result);//即为表达式求值得到的结果 return result;
}int main()
{printf("请输入算术表达式,负数要用(0-正数)仅支持多位数(double)运算 例如:\n");printf("\t\t\t例如 4+8-9*1+(0-3)+9*1/3=\n");printf("表达式的运算结果为:%.2lf\n", EvaluateExpression());return 0;
} 

程序执行的例子

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

msdn画圆弧函数_画直线不简单!python-matplotlib告诉你为什么

1 说明&#xff1a;1.1 python的matplotlib画直线&#xff0c;看似简单&#xff0c;其实很难&#xff0c;从简单到复杂&#xff0c;逐步深入&#xff0c;小白秒懂。1.2 内容&#xff1a;画直线&#xff0c;画圆&#xff0c;画圆点&#xff0c;动画的单摆和圆套圆&#xff0c;好…

Wifi6网络

2020年是Wifi6设备全面爆发的一年&#xff0c;华为、小米、华硕、腾达、TP-LINK、360等多家厂商相继发布了Wifi6路由产品&#xff0c;掀起了一股更换路由器的热潮。首先&#xff0c;我们先来看几个常识1、Wifi6和IPv6两个没有必然联系&#xff0c;Wifi6是一种支持802.11ax的Wif…

数据结构——用栈解决回文字符问题

回文 回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文&#xff0c;但“good”不是回文。试写一个算法判定给定的字符序列是否为回文。&#xff08;提示&#xff1a;将一半字符入栈。&#xff09; 所需的知识前提&#xff1a;栈 以下是顺序栈的基本算法 结构…

aspose excel中文文档_除了VBA,还有哪些编程语言可以操作Excel文件?

Excel(Microsoft office)是现在最常用的办公软件&#xff0c;主要涉及电子表格制作、数据处理、报表输出展示以及更高端的还有金融建模等&#xff1b;我们知道&#xff0c;在需要批处理多个Excel工作表以及工作簿的时候&#xff0c;需要用到一个自动化的利器&#xff1a;VBAVBA…

关于.NET5在IIS中部署的几个问题总结

本来我的系列教程已经慢慢剥离开IIS了&#xff0c;毕竟有了Docker容器以后&#xff0c;配合Nginx使用真的很不错。但是还是有很多同学使用IIS的&#xff0c;这个不可否认IIS的重要性。随着.NET的发布&#xff0c;很多小伙伴已经开始升级了&#xff0c;我也就陆陆续续收到了一些…

数据结构——括号匹配问题

括号匹配 给定一个字符串&#xff0c;其中的字符只包含三种括号&#xff1a;花括号{ }、中括号[ ]、圆括号( )&#xff0c;即它仅由 “( ) [ ] { }” 这六个字符组成。设计算法&#xff0c;判断该字符串是否有效&#xff0c;即字符串中括号是否匹配。括号匹配要求括号必须以正…

wordpress多站点主站调用分站最新文章_企业网站SEO最新的7个优化步骤!

如果你是一个企业主&#xff0c;你有建立企业官方网站的经验&#xff0c;在2-3年的运作中&#xff0c;我相信你至少修改了一个网站&#xff0c;甚至做了一个重大的SEO策略调整。当我们开始建立一个公司的时候&#xff0c;很多时候就是认为只要我们有一个公司的网站&#xff0c;…

Azure 静态 web 应用集成 Azure 函数 API

前几次我们演示了如何通过Azure静态web应用功能发布vue跟blazor的项目(使用 Azure静态web应用Github全自动部署VUE站点、使用Azure静态Web应用部署Blazor Webassembly应用)。但是一个真正的web应用&#xff0c;总是免不了需要后台api服务为前端提供数据或者处理数据的能力。同样…

c++ new一个结构体_C语言结构体,又一个纸老虎,纯干货讲解(附代码)

来源&#xff1a;网络&#xff0c;排版整理&#xff1a;晓宇微信公众号&#xff1a;芯片之家(ID&#xff1a;chiphome-dy)结构体的定义结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合&#xff0c;也叫结构。结构体和其他类型基础数据类型一样&#xff0c…

c语言next的用法,C语言strchr使用之Next查找和截断想要的字符串

#include #include #include #include #include #include #include #include static char pstring[] "Hello\n"; // 这里不能是char*int main(){char tmp ;char* pstr strchr(pstring,‘l‘);printf("pstr is %s %p\n",pstr,pstr);#if 0// 搜后面的pstr …

problem b: 十进制整数转二进制_二进制的科学计数法?白话谈谈计算机如何存储与理解小数:IEEE 754...

浮点数的计算机表示(IEEE 754)&#xff0c;由 UCB 数学教授 William Kahan 主要起草。后者也因其卓越贡献于1989年获得图灵奖。计算机组成原理与汇编语言这两门课均对该内容有所讲解。与课程中直接抛出公式与概念不同&#xff0c;我想首先与各位探讨"科学计数法"这个…

分享我的写作经验

大家好&#xff0c;我是Z哥。最近一段时间&#xff0c;我面基了几个在微信上聊得不错的小伙伴。和其中的两位有聊到关于写作的事情。概括地说就是他们也想写写博客、公众号&#xff0c;但是感觉无从下手。我和他们分享了我的一些经验&#xff0c;在这里做一下总结和补充&#x…

数据结构——二叉树的最小深度算法

给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2 示例 2&#xff1a; 输入&#xff1a;root …

开发板实现645协议C语言,迅为-imx6ull开发板之C语言实现LED例程

第九章我们使用汇编编写了 LED 灯的实验&#xff0c;在实际开发过程中大部分还是使用 C 语言&#xff0c;汇编只是用来完成 C 语言环境的初始化&#xff0c;本章我么就来实现用汇编完成 C 语言环境的初始化&#xff0c;然后用 C 语言实现 LED 的例程。10.1 C 程序版LED例程简介…

解锁环境变量在云原生应用中的各种姿势

应用程序在某些时刻总是需要一些外挂配置&#xff0c;云原生应用的实践是在容器化之前就将应用程序配置保留在代码之外。“12-Factors App&#xff1a;Store config in the environment① 外挂配置文件&#xff1a;业务配置 appsettings.json“可以在代码中要求加载appsetting.…

python字符串截取方法_如何使用python语言中的字符串方法截取字符串

在我们使用python语言中的字符串方法时&#xff0c;可能会判断某个字符串是否以什么开头&#xff0c;可以使用什么进行截取等。下面利用几个实例说明字符串中的方法的用法&#xff0c;操作如下&#xff1a;工具/原料 python 截图工具 方法/步骤 1 第一步&#xff0c;打开python…

数据结构——二叉树的层次遍历

问题描述&#xff1a; 给你一个二叉树&#xff0c;请你返回其按 层序遍历 得到的节点值。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例&#xff1a; 二叉树&#xff1a;[3,9,20,null,null,15,7] 返回其层次遍历结果&#xff1a; [ [3], [9,…

asp.net core 使用 TestServer 来做集成测试

asp.net core 使用 TestServer 来做集成测试Intro之前我的项目里的集成测试是随机一个端口&#xff0c;每次都真实的启动一个 WebServer&#xff0c;之前也有看到过微软文档上 TestServer 的介绍&#xff0c;当时没仔细看过以为差不多就没用&#xff0c;一直是启动了一个真正的…

微服务很香--麻辣味,但要慢慢消化

前言微服务在编程圈火的是不行不行的啦&#xff0c;可能还有很多小伙伴还没有进行微服务实操&#xff0c;但这个词&#xff0c;要说没听过、没看过&#xff0c;那小伙伴一定是假Programmer。虽然微服务很火&#xff0c;但不能盲目使用&#xff1b;先不说涉及技术和工具有多少&a…

c语言实现灰度图像阈值分割,灰度图像--图像分割 阈值处理之平均阈值

学习DIP第52天转载请标明本文出处&#xff1a;http://blog.csdn.net/tonyshengtan &#xff0c;出于尊重文章作者的劳动&#xff0c;转载请标明出处&#xff01;文章代码已托管&#xff0c;欢迎共同开发&#xff1a;https://github.com/Tony-Tan/DIPpro开篇空话好久没写博客了&…