一个算数表达式(以下简称为表达式)由运算数、运算符、左括号和右括号组成,定义一个枚举类型TokenType表示为:

1 typedef enum {
2     BEGIN,
3     NUMBER,
4     OPERATOR,
5     LEFT_BRAC,
6     RIGHT_BRAC
7 } TokenType;

BEGIN用来表示表达式的开始,稍后会再提及到它。

  对表达式进行求值需要借助数据结构栈,C++的标准模板库中包含stack类型,只需要包含头文件stack并引用命名空间std就可以使用了。整个求值过程总共需要2个栈,分别用来存储运算数和运算符;基本求值过程是这样的:比较当前运算符和运算符栈中栈顶运算符的优先级,若栈顶运算符优先级高于当前运算符,则从运算数栈中弹出两个运算数,使用运算符栈栈顶运算符进行计算后再压入运算数栈,并将当前运算符压入运算符栈,否则只将当前运算符压入运算符栈;最后反复上述运算压栈过程直至运算符栈为空,运算数栈的栈顶元素即为运算结果。Calculator类声明如下:

 1 class Calculator
 2 {
 3 public:
 4     double calculate(string expression) throw(string);
 5
 6 private:
 7     stack<double> _stkNumbers;
 8     stack<char> _stkOperators;
 9
10     static int priority(char op);
11     static double calculate(double d1, char op, double d2) throw(string);
12
13     void calculateStack() throw(string);
14     void dealWithNumber(char *&pToken) throw(string);
15     void dealWithOperator(char *&pToken) throw(string);
16     void dealWithLeftBrac(char *&pToken) throw(string);
17     void dealWithRightBrac(char *&pToken) throw(string);
18 };

使用代码描述的运算压栈过程如下:

1 void Calculator::calculateStack() throw (string) {
2     double d2 = _stkNumbers.top();
3     _stkNumbers.pop();
4     double d1 = _stkNumbers.top();
5     _stkNumbers.pop();
6     char op = _stkOperators.top();
7     _stkOperators.pop();
8     _stkNumbers.push(calculate(d1, op, d2));
9 }

静态成员函数calculate()用于进行简单的四则运算,同时也处理了除数为0的情况:

 1 double Calculator::calculate(double d1, char op, double d2) throw (string) {
 2     assert(op == '+' || op == '-' || op == '*' || op == '/');
 3
 4     cout << d1 << op << d2 << endl;
 5
 6     if (op == '+') {
 7         return d1 + d2;
 8     } else if (op == '-') {
 9         return d1 - d2;
10     } else if (op == '*') {
11         return d1 * d2;
12     } else {
13         if (!d2) {
14             throw string("divided by 0");
15         }
16         return d1 / d2;
17     }
18 }

  此外,根据数学规则,有:

  • 表达式只能以左括号或运算数开始;
  • 运算数后只能是右括号或运算符;
  • 运算符或左括号后只能是左括号或运算数;
  • 右括号后只能是另一个右括号或运算符。

使用代码描述这些数学规则和最后清空运算符栈的过程如下:

 1 double Calculator::calculate(string expression) throw (string) {
 2     while (!_stkNumbers.empty()) {
 3         _stkNumbers.pop();
 4     }
 5     while (!_stkOperators.empty()) {
 6         _stkOperators.pop();
 7     }
 8     TokenType lastToken = BEGIN;
 9
10     char * pToken = &expression[0];
11     while (*pToken) {
12         switch (lastToken) {
13         case BEGIN:
14             if (*pToken == '(') {
15                 // an expression begin with a left bracket
16                 dealWithLeftBrac(pToken);
17                 lastToken = LEFT_BRAC;
18             } else {
19                 // or a number
20                 dealWithNumber(pToken);
21                 lastToken = NUMBER;
22             }
23             break;
24         case NUMBER:
25             // after a number
26             if (*pToken == ')') {
27                 // it may be a right bracket
28                 dealWithRightBrac(pToken);
29                 lastToken = RIGHT_BRAC;
30             } else {
31                 // it may be an operator
32                 dealWithOperator(pToken);
33                 lastToken = OPERATOR;
34             }
35             break;
36         case OPERATOR:
37         case LEFT_BRAC:
38             // after an operator or a left bracket
39             if (*pToken == '(') {
40                 // it may be a left bracket
41                 dealWithLeftBrac(pToken);
42                 lastToken = LEFT_BRAC;
43             } else {
44                 // it may be a number
45                 dealWithNumber(pToken);
46                 lastToken = NUMBER;
47             }
48             break;
49         case RIGHT_BRAC:
50             // after a right bracket
51             if (*pToken == ')') {
52                 // it may be another right bracket
53                 dealWithRightBrac(pToken);
54                 lastToken = RIGHT_BRAC;
55             } else {
56                 // it may be an operator
57                 dealWithOperator(pToken);
58                 lastToken = OPERATOR;
59             }
60             break;
61         }
62     }
63
64     while (!_stkOperators.empty()) {
65         if (_stkOperators.top() == '(') {
66             throw string("bad token '('");
67         }
68         calculateStack();
69     }
70
71     assert(!_stkNumbers.empty());
72     return _stkNumbers.top();
73 }

lastToken用来指示上一个token的类型,它应该被初始化为BEGIN;在开始求值之前清空运算符栈和运算数栈,可以防止出错,是很有必要的。

转载于:https://www.cnblogs.com/lets-blu/p/7265961.html

表达式求值(栈方法/C++语言描述)(一)相关推荐

  1. c语言编程实现表达式求值,c语言实现表达式求值的方法

    c语言实现表达式求值的方法 发布时间:2020-06-22 16:45:46 来源:亿速云 阅读:82 作者:Leah 这期内容当中小编将会给大家带来有关c语言实现表达式求值的方法,以专业的角度为大家 ...

  2. c语言作业算术表达式求值,算术表达式求值演示(C语言版)

    //头文件预处理命令 #include #include //----------函数结果状态代码----------------- #define TRUE 1 #define FALSE 0 #d ...

  3. 7-10 逆波兰表达式求值 (20 分)(c语言)(数据结构)

    逆波兰表示法是一种将运算符(operator)写在操作数(operand)后面的描述程序(算式)的方法.举个例子,我们平常用中缀表示法描述的算式(1 + 2)*(5 + 4),改为逆波兰表示法之后则是 ...

  4. 2015 UESTC 数据结构专题N题 秋实大哥搞算数 表达式求值/栈

    秋实大哥搞算数 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/1074 Des ...

  5. c语言求不定式的最大值,C语言之四则运算表达式求值(链栈)—支持浮点型数据,负数, 整型数据运算...

    运算符间的优先级关系: 链栈结构体定义: 数据域使用字符串长度为20的字符数组(故需要注意判断读取的字符串是运算符还是数值) 可支持浮点型数据,负数, 整型数据的运算 float EvaluateEx ...

  6. c语言表达式的算法,表达式求值--数据结构C语言算法实现

    这篇博客介绍的表达式求值是用C语言实现的,只使用了c++里面的引用. 数据结构课本上的一个例题,但是看起来很简单,实现却遇到了很多问题. 这个题需要构建两个栈,一个用来存储运算符OPTR, 一个用来存 ...

  7. 九、表达式求值(1)

    九.表达式求值(1) 文章目录 九.表达式求值(1) 题目描述 解题思路 上机代码 题目描述 背景: 我们的教材中已经介绍了表达式求值的算法,现在我们将该算法的功能进行扩展,要求可以处理的运算符包括: ...

  8. 牛客题霸 [表达式求值] C++题解/答案

    牛客题霸 [表达式求值] C++题解/答案 题目描述 请写一个整数计算器,支持加减乘三种运算和括号. 题解: 没有除法emmm 我们从头开始依次判断每个字符 如果是左括号,我们就找右括号,并截取括号内 ...

  9. 表达式求值(最详细分析+代码实现+表达式之间的相互转换)

    目录 一.概念 二.前缀表达式的逻辑和实现方式 1.定义 2.前缀表达式的计算机求值 3.例子 4.代码实现 三.中缀表达式的逻辑和实现方式 1.定义 2.中缀表达式规则 3.中缀表达式的计算机求值 ...

  10. python前缀表达式求值_python数据结构与算法 11 后缀表达式求值

    从本节开始,删除原版的英文,直接发译后的文稿. 后缀表达式求值 栈的最一个应用例子,计算一个后缀表达式的值.这个例子中仍然用栈的数据结构.不过,当扫描表达式的时候,这次是操作数压栈等待,不是转换算法中 ...

最新文章

  1. 年薪 50w,这门编程语言该怎么学?
  2. java容器类的继承结构
  3. 按不同vlan下发dhcp_电脑网络:交换机VLAN基础知识及基本划分方法,揭开VLAN的面纱...
  4. 第三章:lambda表达式
  5. 分布式理论:CAP是三选二吗?
  6. java 异常处理 简书_Java基础知识8-异常处理
  7. python如何移动图片_Pygame的图像移动|python基础教程|python入门|python教程
  8. php serv-u,用php写的serv-u的web申请账号的程序_php
  9. Oracle 远程 RAC 打造双活数据中心 | 从容灾迈向双活案例分享
  10. 寺库商用区块链落地,联盟链为每件奢侈品发“×××”
  11. 【11月29】PF 粒子滤波的多维运动模型代码
  12. 关于一元线性回归、自相关性与Stata实现
  13. 基于STM32的红外万能遥控器完整教程
  14. 常用编程语言应用、前景及学习方法
  15. Hyperledger Fabric Service Discovery CLI(服务发现命令行工具)学习笔记
  16. python矩阵教程_Python Numpy Tutorial / Python Numpy 教程 (矩阵和图像操作)
  17. NuttX的学习笔记 9
  18. 计算机与航空方向专业,2018航空航天工程专业就业前景和就业方向分析
  19. 怎么把.txt转换成html,怎么把txt转换成HTML
  20. 默纳克调试说明书_默纳克NICE调试说明书修改版

热门文章

  1. mysql悲观锁优化_MySQL事务及实现、隔离级别及锁与优化
  2. python开发怎么成长_Python开发者四大进阶攻略,菜鸟的成神之路
  3. python语言是二进制语言吗_在大型项目上,Python 是个烂语言吗?
  4. C++ multimap 用法总结 例子
  5. Fisco bcos 在多机器上搭建多个节点的区块链网络 教程
  6. FISCO BCOS Solidity 使用Table合约CRUD接口 智能合约例子
  7. 计算机论文-中国免费,计算机硕士毕业论文免费
  8. linux启动hbase_HBase集群环境配置
  9. 远程连接linux主机_Linux远程桌面连接Windows
  10. JavaSE基础———StringBuffer StringBuilder Arrays和基本数据类型包装类