————————————————————————————————————————————

实现原理:

每个操作数都被依次压入栈中,当一个运算符到达时,从栈中弹出相应数目的操作数(对于二元运算符来说是两个操作数),把该运算符作用于弹出的操作数,并把运算结果再压入栈中

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

计算器(后缀表达式)

相关知识:

后缀表达式(逆波兰表示法):在逆波兰中,所有运算符都跟在操作数后面,如下:(1 - 2) *(4 + 5) 采用逆波兰表示法表示为:1 2 - 4 5 + *,不需要圆括号,只要知道每个运算符需要几个操作数就不会引起歧义

实现功能:

输入后缀表达式,以换行结束,计算四则运算结果。

对于 1 2 - 4 5 + * 来说,首先把1和2压入到栈中,再用两者之差-1取代它们;然后将4和5压入到栈中,再用两者之和9取代它们。最后从栈中取出栈顶的-1和9,并把它们的积-9压入到栈顶。到达输入行的末尾时,把栈顶的值弹出来并打印。

伪代码:

while 读入值不为换行时

if 是数字

压入栈中

else if 是运算符

弹出两个运算数,计算并压栈

else 输入错误并退出

end if

读入值

弹出最终结果并打印

实现代码:

 /* 实现功能:输入后缀表达式,以换行结束,计算四则运算结果 */
/* 这种后缀表示法只需要一个栈就可以了,遇到符号则弹运算数,但是中缀就不一样 */
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define STACK_INIT_SIZE 100
#define STACKINCREAMENT 10
typedef int Status;
typedef char SElemType;
typedef struct
{
SElemType *top;
SElemType *base;
int stacksize;
} SqStack;
Status InitStack(SqStack *s)
{
s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!s->base) exit(OVERFLOW);
s->top = s->base;
s->stacksize = STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack *s, SElemType e)
{
if (s->top - s->base == s->stacksize)
{
s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType));
if (!s->base) exit(OVERFLOW);
s->top = s->base + s->stacksize;
s->stacksize += STACKINCREAMENT;
}
s->top++;
*(s->top) = e;
return OK;
}
Status Pop(SqStack *s, SElemType *e)
{
if (s->top == s->base) exit(OVERFLOW);
*e = *(s->top);
s->top--;
return OK;
}
Status Empty(SqStack s)
{
if (s.top - s.base == )
return OK;
else
return ERROR;
}
int main()
{
SqStack OPND; //OPTR是运算符 OPND是运算数
char c, num1, num2;
InitStack(&OPND);
while((c = getchar()) != '\n')
{
switch(c)
{
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
Push(&OPND, c - '');
break;
case '+':
Pop(&OPND, &num2);
Pop(&OPND, &num1);
Push(&OPND, num1 + num2);
break;
case '-':
Pop(&OPND, &num2);
Pop(&OPND, &num1);
Push(&OPND, num1 - num2);
break;
case '*':
Pop(&OPND, &num2);
Pop(&OPND, &num1);
Push(&OPND, num1 * num2);
break;
case '/':
Pop(&OPND, &num2);
Pop(&OPND, &num1);
Push(&OPND, num1 / num2);
break;
default:
break;
}
}
while(!Empty(OPND))
{
Pop(&OPND, &c);
printf("%d ", c);
}
return OK;
}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

计算器(中缀表示法)

运算符优先级:

+

-

*

/

(

)

#

+

>

>

<

<

<

>

>

-

>

>

<

<

<

>

>

*

>

>

>

>

<

>

>

/

>

>

>

>

<

>

>

(

<

<

<

<

<

=

0

)

>

>

>

>

0

>

>

#

<

<

<

<

<

0

=

执行过程:

在计算 #4+3*(5-10)/5# 时栈中的执行过程如下

步骤

输入字符

执行操作

OPTR

OPND

1

#

Push(#)

#

2

4

Push(4)

#

4

3

+

'#'<'+',Push(+)

# +

4

4

3

Push(3)

# +

4 3

5

*

'+'<'*',Push(*)

# + *

4 3

6

(

'*'<'(',Push(()

# + * (

4 3

7

5

Push(5)

# + * (

4 3 5

8

-

'('<'-',Push(-)

# + * ( -

4 3 5

9

10

Push(10)

# + * ( -

4 3 5 10

10

)

'-'>')',计算并压入结果

# + * (

4 3 -5

11

'('=')',脱括号

# + *

4 3 -5

12

/

'*'>'/'计算并压入结果

# +

4 -15

13

'+'<'/',Push(/)

# + /

4 -15

14

5

Push(5)

# + /

4 -15 5

15

#

'/'>'#',计算并压入结果

# +

4 -3

16

'+'>'#',计算并压入结果

#

1

17

'#'='#',脱括号

1

伪代码:

初始化运算符栈;压入#;

初始化运算数栈;获取输入;

while 获取输入不为#或栈顶不为#

if 输入的是数字

压入运算数栈

获取输入

if 新输入的也是数字

十位数百位数运算

end if

else

switch 运算符栈顶与当前输入优先级比较

压入运算符栈

获得输入

弹出运算符栈顶(或#

获得输入

弹出运算符栈顶

弹出两个运算数

计算并将结果压入运算数栈

//此时不获取新输入,该循环输入的运算符作为c重新进入循环

end if

end while

输出运算数栈中剩的运算数

实现代码:

 /* 只能运算-128~127之间的结果 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define OK 1
#define ERROR 0
#define SPILL -2 //math.h中已有OVERFLOW,则改用SPILL
#define STACK_INIT_SIZE 100
#define STACKINCREAMENT 10
typedef char SElemType;
typedef int Status;
typedef struct
{
SElemType *top;
SElemType *base;
int stacksize;
} SqStack;
Status InitStack(SqStack *s)
{
s->base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!s->base)
exit(SPILL);
s->top = s->base;
s->stacksize = STACK_INIT_SIZE;
return OK;
}
Status EmptyStack(SqStack s)
{
if (s.top - s.base == )
return OK;
else
return ERROR;
}
Status Push(SqStack *s, SElemType e)
{
if (s->top - s->base == s->stacksize)
{
s->base = (SElemType *)realloc(s->base, (s->stacksize + STACKINCREAMENT) * sizeof(SElemType));
if (!s->base)
exit(SPILL);
s->top = s->base + s->stacksize;
s->stacksize += STACKINCREAMENT;
}
s->top ++;
*(s->top) = e;
return OK;
}
Status Pop(SqStack *s, SElemType *e)
{
if (s->top == s->base)
exit(SPILL);
*e = *(s->top);
s->top--;
return OK;
}
SElemType GetTop(SqStack s)
{
return *(s.top);
// *e = *(s.top);
// return OK;
}
/* 判断如果是数字则返回OK,运算符返回ERROR,非法输入则退出 */
Status InputJudge(SElemType c)
{
switch(c)
{
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
case '':
return OK;
break;
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case '#':
return ERROR;
break;
default:
exit(SPILL);
break;
}
}
/* 当前输入的运算符和前一个运算符比较优先级 */
SElemType PriorityJudge(SElemType optr1, SElemType optr2)
{
int i, j;
char priorityTable[][] =
{
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', ''},
{'>', '>', '>', '>', '', '>', '>'},
{'<', '<', '<', '<', '<', '', '='}
};
switch(optr1)
{
case '+':
i = ;
break;
case '-':
i = ;
break;
case '*':
i = ;
break;
case '/':
i = ;
break;
case '(':
i = ;
break;
case ')':
i = ;
break;
case '#':
i = ;
break;
}
switch(optr2)
{
case '+':
j = ;
break;
case '-':
j = ;
break;
case '*':
j = ;
break;
case '/':
j = ;
break;
case '(':
j = ;
break;
case ')':
j = ;
break;
case '#':
j = ;
break;
}
return priorityTable[i][j];
}
/* 四则运算 */
SElemType Calc(SElemType optr, SElemType num1, SElemType num2)
{
switch(optr)
{
case '+':
return (num1 + num2);
break;
case '-':
return (num1 - num2);
break;
case '*':
return (num1 * num2);
break;
case '/':
return (num1 / num2);
break;
}
}
int main()
{
char c, optr, num1, num2, temp;
SqStack OPND, OPTR;
InitStack(&OPTR);
Push(&OPTR, '#');
InitStack(&OPND);
c = getchar();
while(c != '#' || GetTop(OPTR) != '#')
// while(!EmptyStack(OPTR))
//严蔚敏老师书上的算法是判断输入非#或栈顶非#时循环,个人认为判断运算符栈不为空也可以,当初始化时压入的#闭合,结束运算
{
if (InputJudge(c))
{
Push(&OPND, c - '');
c = getchar();
/* 当连续输入数字时,计算十位数和百位数 */
while(InputJudge(c))
{
int i = ;
Pop(&OPND, &temp);
Push(&OPND, temp * pow(, i) + (c - ''));
i++;
c = getchar();
}
}
else
switch(PriorityJudge(GetTop(OPTR), c))
{
case '<':
Push(&OPTR, c);
c = getchar();
break;
case '=':
Pop(&OPTR, &c);
c = getchar();
break;
case '>':
Pop(&OPTR, &optr);
Pop(&OPND, &num2);
Pop(&OPND, &num1);
Push(&OPND, Calc(optr, num1, num2));
break;
}
}
while(!EmptyStack(OPND))
{
Pop(&OPND, &c);
printf("%d\n", c);
}
return OK;
}

C语言 | 计算器实现(中缀表示法/后缀表示法)的更多相关文章

  1. .net表达式计算器(中缀表达式转后缀表达式,支持20多个数学函数,支持函数嵌套)

    最近在网上查了一下表达工计算器的类库,发现Java版本的有一个比较成熟的叫W3EVal,好像是一个IBM工程师写的,.net就很少了(可能是我了解不够多),但投机取巧的实现思路有很多,比如: (1)将 ...

  2. 3-06. 表达式转换(25)(中缀表达式转后缀表达式ZJU_PAT)

    题目链接:http://pat.zju.edu.cn/contests/ds/3-06 算术表达式有前缀表示法.中缀表示法和后缀表示法等形式. 日常使用的算术表达式是採用中缀表示法,即二元运算符位于两 ...

  3. 栈的应用1——超级计算器(中缀与后缀表达式)C语言

    这里要学的程序主要用来实现一个功能——输入表达式输出结果,也就是一个计算器.效果如下: 这个程序主要有两个步骤:1.把中缀表达式转换为后缀表达式:2.计算后缀表达式的结果. 首先先明白几个问题: 1. ...

  4. c语言,中缀表达式转后缀表达式并计算

    //c语言中缀表达式计算 #include <stdio.h> #include <stdlib.h> #include <string.h> #include & ...

  5. 栈的简单应用之中缀表达式转后缀表达式(C语言实现逆波兰式)

    一.前言   普通人在书写计算式时会选择中缀表达式,这样符合人脑的认知习惯.可计算机处理时后缀表达式才能使处理速度更快,其原因是利用堆栈结构减少计算机内存访问.同时它也是一个很好锻炼栈这个数据结构的应 ...

  6. 数据结构之栈—强大的四则复杂运算计算器(超过windows自带的科学计算器)【中缀转后缀表达式】

    比windows自带计算器还强的四则复杂运算计算器! 实测随机打出两组复杂算式:-7.5 * 6 / ( -2 + ( -6.5 -  -5.22 ) )与7.5+-3*8/(7+2) windows ...

  7. RPN-逆波兰计算器-中缀表达式转后缀表达式-javascript

    1.利用栈(Stack)来存储操作数和操作符: 2.包含中缀表达式转后缀表达式的函数,这个是难点,也是关键点: 2.1.将输入字符串转为数组: 2.2.对转换来的字符进行遍历:创建一个数组,用来给存储 ...

  8. hdu-1237 简单计算器---中缀表达式转后缀表达式

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1237 题目大意: 读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值. 思路 ...

  9. C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611

    09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...

随机推荐

  1. entitymanager 进行数据序列化

    场景:同一个方法里,需要将前一部分执行的数据保存到数据库.后半部分读取数据时从数据库里获取,而不是获取到缓存里的数据. 理解eneityManager的这三个方法的作用和区别,首先需要分清楚Persi ...

  2. django视图重定向

    # 原创,转载请留言联系 当请求访问到某个视图时,我们想让它重定向到其他页面,应该怎么做呢? 1.HttpResponseRedirect 需求:当我们访问127.0.0.1/my_redirect时 ...

  3. centos6.6部署mysql mmm高可用架构

    一.环境简述 1.工作逻辑图 2.MySQL-MMM优缺点 优点:高可用性,扩展性好,出现故障自动切换,对于主主同步,在同一时间只提供一台数据库写操作,保证的数据的一致性. 缺点:Monitor节点是 ...

  4. 解析 Lambda 表达式

    我们先创建一个表达式树: Expression<Func<int, int, int>> expression = (a,b) => a + b; 我们的例子是一个Exp ...

  5. HDU 1394.Minimum Inversion Number-最小逆序数-完全版线段树(单点增减、区间求和)

    HDU1394.Minimum Inversion Number 这个题求最小逆序数,先建一个空的树,然后每输入一个值,就先查询一下,查询之后,更新线段树,然后遍历一遍,每次将第一个数放到最后之后,减 ...

  6. AppScan入门工作原理详解

    AppScan,即 AppScan standard edition.其安装在 Windows 操作系统上,可以对网站等 Web 应用进行自动化的应用安全扫描和测试. Rational AppScan ...

  7. apache和tomcat群集

    httpd.conf    httpd.conf中添加:    #与tomcat的插件    include "D:\clusterServer\apache\conf\mod_jk.con ...

  8. POJ 2914 Minimum Cut (全局最小割)

    [题目链接] http://poj.org/problem?id=2914 [题目大意] 求出一个最小边割集,使得图不连通 [题解] 利用stoerwagner算法直接求出全局最小割,即答案. [代码 ...

  9. skywalking学习

    skywalking简介 SkyWalking一个开源可观测性平台,用于收集.分析.聚合和可视化来自服务和云原生基础设施的数据.SkyWalking提供了一种简单的方法,可以让你清晰的查看分布式系统. ...

  10. Shader与AGAL(From 7yue)