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

实现原理:

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

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

计算器(后缀表达式)

相关知识:

后缀表达式(逆波兰表示法):在逆波兰中,所有运算符都跟在操作数后面,如下:(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. Linux内核中的中断栈与内核栈的补充说明【转】

    转自:http://blog.chinaunix.net/uid-12461657-id-3487463.html 原文地址:Linux内核中的中断栈与内核栈的补充说明 作者:MagicBoy2010 ...

  2. Linux SPI总线和设备驱动架构之一:系统概述【转】

    转自:http://blog.csdn.net/droidphone/article/details/23367051/ 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 硬 ...

  3. 纠正网上乱传的android调用Webservice方法。

    1.写作背景: 笔者想实现android调用webservice,可是网上全是不管对与错乱转载的文章,结果不但不能解决问题,只会让人心烦,所以笔者决定将自己整理好的能用的android调用webser ...

  4. (转) view视图的放大、缩小、旋转

    控件移动,放大,缩小,旋转 1,代码添加控件 例如: /* 1.创建一个控件 2.设置控件的位置,大小 3.设置控件所需要的各个属性 4.添加入父控件 5.添加监听 */ UIButton *btn1 ...

  5. 分金币 Uva 11300

    题意 给定N个人成环状坐,每个人初始分配Ai的金币,金币总数可以被N整除,每个人可以给左右相邻的人一定数量的金币使得最终每个人的金币数量相同,求转移数量最小的方案所转移的总金币数量. N<=10 ...

  6. Mac如何通过远程控制其他Mac

    Mac如何通过远程控制其他Mac 发表于 2012 年 10 月 15 日 很多时候,我们会碰到需要被别人远程帮助或者远程帮助别人的情况,Windows下我们可以通过远程连接或者QQ远程协助来完成,但 ...

  7. Matlab中find函数陷阱

    a = [ 1 2 3 3  3]; 如果a==3 返回[ 0 0 1  1 1]; find(a==3) 返回[3 4 5],这才是想要的下标.

  8. Android可伸缩列表ExpandableListView

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  9. github 丢失的本地提交

    open git bash git reflog git reset xxxxxxx

  10. SVM相关知识及和softmax区别

    1.相对于容易过度拟合训练样本的人工神经网络,支持向量机对于未见过的测试样本具有更好的推广能力. 2.SVM更偏好解释数据的简单模型---二维空间中的直线,三维空间中的平面和更高维空间中的超平面. 3 ...