计算器的设计
计算器主要功能是根据用户的输入,进行适当的计算。里面需要有内置函数、变量记录功能。
根据需要,我们可以大致抽象出一些对象来:
解析器:负责解析式子,目标是将输入的字符串转换成一个算术树,逆波兰序
符号表:记录出现过的符号(符号包括:变量名、内置函数、内置常量)
扫描器:从左往右的扫描缓冲器并将它们转换成记号
存储器:存储着变量的值
函数表:存储着一些内置函数
采用自顶向下设计的设计方法,下面是顶层的结构:
{
函数表:FunctionaTable
存储表:Store
While(true)
1.读取用户输入
2.创建扫描器Scanner
3.创建解析器Parser
4.获得值Eval
}
现在开始逐渐完善上面的函数
扫描器功能分析:
扫描器需要有什么功能呢?扫描器需要对用户的输入进行解析,根据输入给出记号,具体怎么处理记号不归扫描器的管。
我们以一个简单的式子来说明,扫描器需要有的功能:
B=3+4/5-7*4+a-c
上面这个式子里有加减乘除、还有变量,所以扫描器应该要能识别不同的运算符,然后提供提取数字、变量的功能。
抽象出来其提供的接口有
{
Token()返回记号
Accept()解析下一个记号
Number()返回数字
GetSymbolName()返回变量名
}
符号表是负责记录了所有出现的符号,包括变量名、函数名、内置变量。
符号表的功能:
1、添加符号 ---------------返回符号的标识符
2、查找符号 --------------返回标识符
3、获得符号 --------------根据标识符得到符号
根据上面的要求,我们可能的实现是什么呢?
我们对符号应该有唯一的id标识,,然后 字符串 – id 这个可以用hash表实现,但是 id 到 字符串怎么可以快速实现呢?我们可以记录下这种关系,即id – 字符串的关系即可,我们可以通过下面的结构表示:
哈希表【HTabl】 ---------- 提供 字符串 ----- Ids
字符串表[StringBuffer]---------提供 偏移-----------字符串
偏移记录表----------------------提供-------id----------------偏移
偏移记录表 通过 id 来 得到在StringBuffer表中的偏移
由上图我们可以大致了解数据结构了:
符号表中有几个重要的对象
Hash表:记录了 string ------ id 对应关系
字符串表:记录了 不同的identifier
偏移表 :记录了 id -------- 偏移 对应关系
功能
Eval()
{
1.递归解析式子
2.计算值
}
首先介绍一些基本概念:
1、表达式 expression
a.是一个后面有加号或者减号的项,加号或者减号后面又是另一个表达式
b.如果表达式不含有任何减号或者加号,它等于此项
c.表达式也可以为一个项加一个等于号,再加上一个表达式
// expression is Term + experssion
// or Term - expression
// or Term = expression
// or just Term
2、项 term
a.被另一个项乘或者除的因子
b.如果一个项不包含任何乘或者除运算符,它等于此因子
// term is Factor * Term
// or Factor / Term
// or just Factor
3、因子 factor
a.一个数组
b.一个对应于某变量的标识符
c.后面带有一个因子的减号
d.小括号中的整个表达式
根据上面的说明,我们就可以设计出解析器了,根据上面的规则
提供几个函数
{
void Parse();
Node * Expr();
Node * Term();
Node * Factor();
}
根据上面的需求我们可以就可以开始具体实现了。