一个简单的计算器

一个简单的计算器

代码位置:

https://github.com/DennisThink/Calculater

具体介绍:

最近看完了《Effective Morden C++》,里面主要讲解了 C++11/14 的一些的用法,但是暂时想不到用什么项目来写,就把大学的时候实现的一个计算器又做了一遍,顺便用到了刚刚学到的新知识,算是学以致用吧。这篇文章主要对这个计算器的项目做一个介绍,方便大家理解代码和进行扩展,闲话少说,言归正传。

## 1. 整体设计

1.1 逻辑设计

计算器的整体设计思路采用的算符优先文法,也就是确定算符的优先级,然后对该算符两侧的运算数进行运算,结果为一个运算数,然后采用递归的方法进行。

算符优先表

左侧算符 右侧算符 优先级
ADD_LEVEL ADD_LEVEL LEFT_HIGH
ADD_LEVEL MUL_LEVEL RIGHT_HIGH
ADD_LEVEL LEFT_BRACKET RIGHT_HIGH
ADD_LEVEL RIGHT_BRACKET LEFT_HIGH
——- ——– ——
MUL_LEVEL ADD_LEVEL LEFT_HIGH
MUL_LEVEL MUL_LEVEL LEFT_HIGH
MUL_LEVEL LEFT_BRACKET RIGHT_HIGH
MUL_LEVEL RIGHT_BRACKET LEFT_HIGH
——- ——– ——
LEFT_BRACKET ADD_LEVEL RIGHT_HIGH
LEFT_BRACKET MUL_LEVEL RIGHT_HIGH
LEFT_BRACKET LEFT_BRACKET RIGHT_HIGH
LEFT_BRACKET RIGHT_BRACKET EQUAL
——- ——– ——
RIGHT_BRACKET ADD_LEVEL LEFT_HIGH
RIGHT_BRACKET MUL_LEVEL LEFT_HIGH
RIGHT_BRACKET LEFT_BRACKET ERROR
RIGHT_BRACKET RIGHT_BRACKET LEFT_HIGH

1.2 代码的设计

代码的整体架构的设计如下:

token

1.3 整体流程

  1. 解析运算运算式为Tokens。
  2. 是否为( Number )的形式
  3. 是,结束运算,结果为Number。
  4. 不是,从左到右寻找三个连续的运算符,他们的优先级为 Left < MediumMedium > Right,然后对Medium运算符左右的运算数进行运算,运算的结果替代 LeftNum Medium RightNum的位置。
    然后跳转到第2步。

2. 举例说明

举个例子
例如对于 2+3*4-5的分析处理过程如下
1. 第一步进行表达式分析,将表达式分析为符号表,分析后的结果如下。

原表达式 符号 类型
2 2 运算数
+ ADD 加法运算符
3 3 运算数
* MUL 乘法运算符
4 4 运算数
SUB 减法运算符
5 5 运算数

为了方便运算,将表达式分析结果放在括号里,即最后的分析结果为

原表达式 符号 类型
( ( 左括号
2 2 运算数
+ ADD 加法运算符
3 3 运算数
* MUL 乘法运算符
4 4 运算数
SUB 减法运算符
5 5 运算数
) ) 右括号运算符
  1. 按照 1.3流程,这个表达式的分析过程如下

3. 代码展示

3.1 CToken的代码

对于CToken来说,主要有两个作用

  • 将字符串形式的表达式,表示为解析后的Token列表。
  • 对数字和运算符提供抽象。

3.2 CTokenNumber的代码

对于CTokenNumber来说,主要是用来表示表达式中的数字,用到的C++的知识点。

  • namespace —-因为继承自CToken,所以将其放在与 CToken相同的命名空间下。
  • overrite —-因为CTokenNumber,重写了CTokentoString()方法,使用override关键字,可以让编译器进行检查,以防止重写错误。
  • final —-因为toString()没有被重写的需求,所以此处将方法声明为final,防止被子类重写。

3.3 TokenOperator的代码

TokenOperator为所有运算符的父类,相对于CToken,这个类多提供三个函数。

  • getOperatorType() ,获取运算符类型,最初的设计是为了做运算符的优先级的比较的。现在只作为运算符的类型标识。
  • getOperatorPriority(),获取运算符的优先级级别,用于运算符优先级的比较,确定需要进行计算的运算符。
  • TokenNumber compute(const TokenNumber& lhs,const TokenNumber& rhs),对运算数进行计算。
  • virtual func()=0 —-声明虚函数=0,说明此类不提供虚函数的实现,且不可以进行实例化。

除非注明,否则均为浮生笔记原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.dennisthink.com/2019/01/04/84/

One thought on “一个简单的计算器

Leave a Reply

Your email address will not be published. Required fields are marked *