C语言堆栈应用之逆波兰法表达式求值

前言:大学的时候为了更好的理解栈的应用,写了个基于堆栈的表达式求值程序,今天搬上来,修行尚浅,不喜勿喷

一、实现功能

在窗口中输入要求的表达式,实现表达式的求值计算,包括带“()”的表达式,以及小数表达式的求值,基本得以实现。经程序处理计算后输出结果

效果如下

二、 算法概述

假设有两个栈:snum(用来存放运算数)、sope(用来存放符号);

假设现有一表达式:3+2*4+6/(2+1),求值过程如下:

​ 1. 判断是数字还是字符(±*/ ()),是数字就入到snum栈。

​ 2. ①若是字符‘+’‘-’‘*’‘/’ ‘(’时调用处理函数进行入栈或计算处理:(a).若sope栈空或现在取到的符号为‘(’时入栈(b).获得sope栈顶元素的值并与现在取到字符进行优先级比较:如果现在的字符(运算符)的优先级小于SOpe栈顶元素的值的优先级,那么从snum中取出两个数字与现在字符进行计算,把得到结果入栈;否则将字符入到sope栈
②当出现‘)’,取出sope中的栈顶元素(运算符)和snum中的两个数字进行相应计算,计算结果再次入栈并把sope的栈顶元素(’)’)出栈。

​ 3. 在字符中没有出现字符串结束标识符(‘\0’)时,重复1、2步。

​ 4. 对输入表达式(字符串),进行处理完后,若sope栈未空,则从snum取出两个数字、从sope中取出运算符进行计算处理,计算结果再入栈。

当sope为空栈时,从snum取出最后结果并输出结果。

三、 源代码

废话不多说,下面直接上源代码,程序不多,都有注释,不在一一解释。

#define.h头文件 #

#ifndef define_header
#define define_header
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<math.h>#define STACK_INIT_SIZE 100//定义栈的初始分配空间
#define STACKINCRENMENT 10//栈的分配增量//定义栈
typedef struct
{double *top;//栈顶double *base;//栈底int stacksize;//当前栈的大小
}stack;stack *creatorStack(stack *s);//创建并初始化栈
stack *clearStack(stack *s);
void push(stack *s,double e);//入栈
void pop(stack *s,double *e);//出栈void deal_ope(stack *snum,stack *sope,double ope);//符号出现+ - * /( 时处理函数
void deal_bracket(stack *snum,stack *sope);//符号出现) 时处理的函数
int get_pri(double ope);//获取符号优先级
void compute(stack *snum,double ope);//计算函数
int stack_is_empty(stack *L);//判断是否为栈空函数
int Get_Top(stack *S, double *e) ;//获取栈顶元素
int f_int(double a);//浮点型转int型函数
#endif

#man.c文件#

#include"define.h"
int main()
{stack snum,sope;int i=0,j=0;double value1=0,value=0;int flag_shuzi=0,flag_dian=0;double old_ope=0,t;char str[32];creatorStack(&snum);creatorStack(&sope);printf("###################欢迎您使用表达式求值计算器#####################\n###################2017年10月25日#################################\n");
printf("请输入表达式,然后按回车键进行计算:\n");while(1){gets(str);while (str[i]!= '\0'){//获取输入的数字if((str[i] >= '0' && str[i] <= '9')||str[i]=='.'){//value = value * 10 + str[i] - '0';value1=str[i]-'0';if(str[i]=='.')  //str[i]为‘.’时,说明是小数进行处理,并把此时的value1置0;保证valu不变{flag_dian=1;value1=0;}if(flag_dian){t=1/(pow(10.0000,j));    //字符串转为小数的数值value=value+value1*t;j++;}elsevalue=value*10+value1;//非小数点if ((str[i+1] < '0' || str[i+1] > '9')&&str[i+1]!='.'){flag_shuzi = 1;flag_dian=0;j=0;} }else//ope{if (flag_shuzi)//value里面存储了数字,将其入栈{push (&snum, value);flag_shuzi = 0;//清0value1=value=0;}if(str[i] == ')')// )出现时的处理{deal_bracket(&snum,&sope);}else //+-*/( 等情况 {deal_ope(&snum,&sope,str[i]);} } i++; } //如果flag_shuzi = 1.说明还有数值,将其入栈if (flag_shuzi){push(&snum,value);flag_shuzi=0;} while (!stack_is_empty(&sope)){pop(&sope,&old_ope);compute(&snum,old_ope);}value=0;i=0;pop(&snum,&value);//取出结果、打印结果printf("%s = %f\n",str,value); value1=value=0;memset(str,0,32);printf("请再次输入:\n");}return 1;
}

#method.c文件#

#include"define.h"
void deal_ope(stack *snum,stack *sope,double ope)
{double old_ope;//如果sope符号栈是空栈或者符号为‘(’if (stack_is_empty(sope) || (f_int(ope)) == '('){//将括号(入栈push(sope,ope);return ;}//获得当前的符号栈的栈顶Get_Top(sope,&old_ope);if (get_pri(ope) > get_pri(old_ope))//传入符号大于当前栈顶,则将传入符号入栈{      push(sope,ope);return ;    }while (get_pri(ope) <= get_pri(old_ope)) //如果传入的符号优先级小于当前栈顶符号{//将当前栈顶的符号取出与数字栈中顶端的两个数字进行计算pop(sope,&old_ope);compute(snum,old_ope);if (stack_is_empty(sope)){break;}Get_Top(sope,&old_ope);}push(sope,ope);
}
/*如果检测到符号时')',则执行该函数,参数为数字栈和符号栈*/
void deal_bracket(stack *snum,stack *sope)
{double old_ope;//获得当前的符号栈的栈顶符号Get_Top(sope,&old_ope); while ((f_int(old_ope)) != '('){   pop(sope,&old_ope);     //当前符号出栈然后将数字出栈两个进行计算,在括号内优先级最高,compute(snum,old_ope);Get_Top(sope,&old_ope);//然后再次取出当前符号栈栈顶符号,至到出现‘(’   }pop(sope,&old_ope);//最后将出现的左扩号出栈丢弃
}
int get_pri(double ope) //获取运算符的优先级
{switch(f_int(ope)){case '(':   return 0;break;case '+':case '-':   return 1;break;case '*':case '/':   return 2;break;default :   return -1;break;}
}void compute(stack *snum,double ope)/* 将两个数出栈、根据ope符号计算,然后再次入栈 */
{double n,n1,n2;pop(snum,&n2);//依次获得数值栈的栈顶两个数pop(snum,&n1);switch(f_int(ope)) //计算{case '+':   n = n1 + n2; break;case '-':   n = n1 - n2; break;case '*':   n = n1 * n2; break;case '/':   n = n1 / n2; break;}push(snum,n); //计算完再入栈n=n1=n2=0;
}
int f_int(double a) //浮点型数据转为整型数据
{int b;b=a;return b;
}

#SqStack.c文件#

#include"define.h"
stack *creatorStack(stack *s)
{s->base=(double*)malloc(STACK_INIT_SIZE *sizeof(double));if(NULL==s) //假设s没有分配成功{exit(-1);}s->top=s->base;//初始化栈s->stacksize=STACK_INIT_SIZE;
}stack *clearStack(stack *s)//清空栈
{if(NULL==s->base){printf("\n Sorry, stack does not exist!\n");return ;}s->top=s->base;return s;
}void push(stack *s,double e)//进栈操作
{if((s->top-s->base)>STACK_INIT_SIZE) //s是否已满,若栈满,重新分配空间{s->base=(double*)realloc(s->base,(STACKINCRENMENT+STACK_INIT_SIZE)*sizeof(double));if(NULL==s->base){return;}//将栈顶指针指向栈顶s->top=s->base+s->stacksize;s->stacksize+=STACKINCRENMENT;}*(s->top)=e;//将元素e,写入栈顶s->top++;
}void pop(stack *s,double *e)//出栈
{if(s->top==s->base){exit(-1);}s->top--;*e=*(s->top);
}
int stack_is_empty(stack *s)//判断栈是否为空
{return (s->top ==s->base);
}
int Get_Top(stack *S, double *e) //获取栈点元素
{  if(S->top == S->base)  return -1;  else *e=*(S->top-1); return 1;
}

C语言堆栈应用之逆波兰法表达式求值相关推荐

  1. C语言编程对一个逆波兰式进行求值,算式与逆波兰式

    致憨憨的从前 当年,老师布置一道作业:编写一个计算器,要求输入算式,给出结果.算式中只包含+-*/^这几个运算符,算式中不含负数.由于是Python课程,我很快给出了解题方式,如下: while Tr ...

  2. Leetcode 逆波兰式表达式求值

    class Solution {     public int evalRPN(String[] tokens) {         Stack<Integer> stack = new ...

  3. 【Java】LeetCode 150. 逆波兰表达式求值 (后缀表达式)

    题目: 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总是有效的.换句话 ...

  4. LetCode: 150. 逆波兰表达式求值

    提示 LintCode中的相关算法题实现代码,可以在我的GithHub中下载. 题目需求 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另 ...

  5. 使用栈解决的一类经典问题:表达式转换及求值;中缀表达式;前缀表达式,后缀表达式,中缀转前缀;中缀转后缀;后缀表达式求值;波兰式,逆波兰式

    文章目录 背景知识 表达式转换问题(考研经典) 一:手工转换 (1)中缀转前缀和中缀转后缀 (2)前缀转中缀和后缀转中缀 二:用栈实现表达式转换 (1)中缀转后缀 (2)中缀转前缀 表达式计算问题(使 ...

  6. leetcode_150. 逆波兰表达式求值

    一.题目内容 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.* ./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总是有效的 ...

  7. 波兰式、逆波兰式与表达式求值

    波兰式.逆波兰式与表达式求值 <数据结构>中关于栈的解释经常会涉及到逆波兰式,波兰式,中缀式表达式的求值问题.但是,十分惭愧,整个大一阶段, 数据结构的课程没有上够5节,没有意识要学习,吃 ...

  8. 代码随想录第11天 | LeetCode20. 有效的括号、LeetCode1047. 删除字符串中的所有相邻重复项、LeetCode150. 逆波兰表达式求值

    day11 | LeetCode20. 有效的括号.LeetCode1047. 删除字符串中的所有相邻重复项.LeetCode150. 逆波兰表达式求值 文章目录 day11 | LeetCode20 ...

  9. 算法训练第十一天|力扣20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值

    20. 有效的括号 题目链接:有效的括号 参考:https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B ...

  10. 栈的应用(递归:例子裴波那契数列 四则运算表达式求值 :后缀(逆波兰) )

    递归: -栈有一个很重要的应用:在程序设计语言中实现递归. 当你往镜子前面一站,镜子里面就有-一个你的像. 但你试过两面镜子一起照吗?如果A.B两面镜子相互面对面放着,你往中间- -站,嘿,两面镜子里 ...

最新文章

  1. python 微信爬虫_python3简单实现微信爬虫
  2. 交换器无法根据自身类型和路由键找到符合条件队列时,有哪些处理?
  3. bugku ctf 域名解析
  4. 易优cms后台RCE以及任意文件上传漏洞
  5. 直击阿里新一代数据库技术:如何实现极致弹性能力?
  6. 华为2017年财报,为何6036亿销售收入,净利润才479亿?
  7. 理解卷积神经网络的利器:9篇重要的深度学习论文(下)
  8. 2021,我的年终总结......
  9. Java8刚刚普及,Java12即将发布,程序员吐槽学不动求慢一点
  10. WTG--让我们随时随地封装系统!
  11. Javascript(八)javascript页面重定向
  12. Python Selenium 抓取Shadow Dom内部元素方法更新
  13. 【Matlab车牌识别】BP神经网络车牌识别【含GUI源码 669期】
  14. 一些看完让你受益匪浅的英语学习文章和常识(推荐看一下)
  15. Arduino应用开发——LCD显示GIF动图
  16. 我的Java学习之路2009-11-17
  17. 12.16 Day 1 - 分布式系统架构的冰与火
  18. 永久屏蔽警告:grep: warning: GREP_OPTIONS is deprecated; please use an alias or script
  19. Hbuilder-应用程序打包
  20. 学习人工智能需要哪些必备基础

热门文章

  1. bugzilla dbd-mysql_Ubuntu搭建bugzilla
  2. 约束,修改表结构,添加删除约束
  3. 微型计算机中一个字节由2位组成,一个字节由几个二进制位组成
  4. Excel 预习阶段Day4
  5. 计算机取证之Xplico ——合天网安实验室学习笔记
  6. 水水的证件-身份证、证件加水印小工具
  7. 运维工作5年简历写成这样,谁敢要你
  8. js判断文件后缀名方法
  9. 回归分析结果表格怎么填_excel回归分析结果解读
  10. 具有层级关系的关系型数据库表设计