小型计算器A small software project

来源:互联网 发布:javascript 现状 编辑:程序博客网 时间:2024/06/05 21:51

小型计算器

一个小型的软件项目,代码大概1000行左右,包括了很多知识(继承、多态、前向声明、虚函数、动态内存、引用、指针等等),从头到尾写完花了些时间,但觉得很受用。
(1)计算器程序的目的是接受用户提供的算术表达式(例:1+2*3),求其值显示结果。
(2)每个算术表达式由解析器分析,将输入的算法表达式(一串字符)转换成一个算术树。
(3)算术树(一种数据结构):算术表达式可以转换为一个二叉树结构。
如:(a+b×(c-d))-e/f
二叉树结构为:
这里写图片描述

解析器语法

解析式寻找一个表达式,语法定义如下:
1. An expression is(一个表达式是)
a. 一个后面有加号或减号的项,加号或减号后面是另一个表达式。例:表达式2-3,2是一个项(后面是减号),3是一个表达式。
b. 如果表达式不含有加号、减号,它等于项。
(例:上例中的3是一个表达式,它也是一个项)

2. A term is(一个项是)
a. 被另一个项乘除的因子。
(例:表达式1+2*3,2*3是一个表达式,满足1b条件,2*3是一个项,满足2a条件,2是一个因子)
b.项如果不包含乘除,它等于此因子。

3. A factor can be(一个因子是)
a. 数字
b. 对应某变量的标识符
c. 后面带有一个因子的减号
d. 小括号中的整个表达式

配合实例理解解析器的语法定义:
1+x*(2-y)
这里写图片描述

具体实现

计算器由以下几个对象组成:
(1)扫描器,扫描用户输入的字符串。
(2)符号表,使计算器可以处理符号变量,如(x=1,变量x代表1)
(3)存储器,让计算器具有记忆能力,可以保存用户自定义变量的值。
(4)函数表,让计算器事先具有一些函数(如sin、cos、log、exp)
(5)结点,对应算术树的每个结点(使用继承实现)。关于结点的简化版本参看C++多态
(6)解析器,实现算数表达式的解析。

代码:只给出主函数、解析器代码,剩下的代码可以从github下载。
计算器Github
主函数 calculator.cpp

#include"SymbolTable.h"#include"FunctionTable.h"#include"Store.h"#include"Scanner.h"#include"Parser.h"const int maxBuf = 100;const int maxSymbols = 40;int main(){    char buf[maxBuf];    //状态位    Status status;    //符号表    SymbolTable symTab(maxSymbols);    //函数表    FunctionTable funTab(symTab, funArr);       //存储器    Store store(maxSymbols, symTab);    do    {        std::cout << "> ";        std::cin.getline(buf, maxBuf);        //扫描器        Scanner scanner(buf);        //解析器        Parser parser(scanner, store, funTab, symTab);        status = parser.Eval();    } while (status != stQuit);    return 0;}

解析器 Parser.h

#ifndef PARSER_H#define PARSER_Hclass Node;class Scanner;class SymbolTable;class Store;class FunctionTable;//枚举:状态enum Status{    stOK,    stQuit,    stError};//解析器类class Parser{public:    Parser(Scanner & scanner,        Store& store,        FunctionTable& funTab,        SymbolTable & symTab);    ~Parser();    Status Eval();private:    void Parse();    Node* Expr();    Node* Term();    Node* Factor();    void Execute();    Scanner & _scanner;//扫描器    SymbolTable & _symTab;//符号表    Node* _pTree;//算术树    Status _status;//状态位    Store& _store;//存储器    FunctionTable& _funTab;//函数表};#endif

Parser.cpp

#include "Parser.h"#include<iostream>#include"Store.h"#include"Node.h"#include"FunctionTable.h"#include"SymbolTable.h" #include"Scanner.h"#include"AddNode.h"#include "AssignNode.h"#include"SubNode.h"#include"MultNode.h"#include"DivideNode.h"#include"NumNode.h"#include"FunNode.h"#include"VarNode.h"#include"UMinusNode.h"Parser::~Parser(){    delete _pTree;}       Parser::Parser(Scanner & scanner,    Store& store,    FunctionTable& funTab,    SymbolTable & symTab)    :_scanner(scanner),    _pTree(0),    _status(stOK),    _funTab(funTab),    _store(store),    _symTab(symTab){    std::cout << "Parser Created" << std::endl;}//解析记号Status Parser::Eval(){    Parse();    if (_status == stOK)        Execute();    else        _status == stQuit;    return _status;    //for (EToken token = _scanner.Token();    //  token != tEnd;    //  _scanner.Accept())    //{    //  token = _scanner.Token();    //  switch (token)    //  {    //  case tMult:    //      std::cout << "Times" << std::endl;    //      break;    //  case tPlus:    //      std::cout << "Plus" << std::endl;    //      break;    //  case tNumber:    //      std::cout << "Number: " << _scanner.Number() << std::endl;    //      break;    //  case tEnd:    //      std::cout << "End" << std::endl;    //      return stQuit;    //  case tError:    //      std::cout << "Error" << std::endl;    //      return stQuit;    //  default:    //      std::cout << "Error: bad token" << std::endl;    //      return stQuit;    //  }    //}    //return stOK;}void Parser::Execute(){    if (_pTree)    {        double result = _pTree->Calc();        std::cout << " " << result << std::endl;    }}void Parser::Parse(){    _pTree = Expr();}//表达式Node* Parser::Expr(){    Node* pNode = Term();    EToken token = _scanner.Token();    //加    if (token == tPlus)    {        //识别下一个记号        _scanner.Accept();        Node* pRight = Expr();        pNode = new AddNode(pNode, pRight);    }    //减    else if (token==tMinus)    {        _scanner.Accept();        Node* pRight = Expr();        pNode = new SubNode(pNode, pRight);    }    //赋值    else if (token == tAssign)    {        _scanner.Accept();        Node* pRight = Expr();        //左值        if (pNode->IsLvalue())        {            pNode = new AssignNode(pNode, pRight);        }        else        {            _status = stError;            delete pNode;            pNode = Expr();        }    }    return pNode;}//项Node* Parser::Term(){    Node* pNode = Factor();    //Term is Factor * Term    if (_scanner.Token() == tMult)    {        _scanner.Accept();        Node* pRight = Term();        pNode = new MultNode(pNode, pRight);    }    //Term is Factor/Term    else if (_scanner.Token()==tDivide)    {        _scanner.Accept();        Node* pRight = Term();        pNode = new DivideNode(pNode, pRight);    }    //Term is Factor    return pNode;}//因子Node* Parser::Factor(){    Node* pNode;    EToken token = _scanner.Token();    //左括号    if (token == tLParen)    {        _scanner.Accept();//accept '('        pNode = Expr();        if (_scanner.Token() != tRParen)            _status = stError;        _scanner.Accept();//accept ')'    }    //数字    else if (token == tNumber)    {        pNode = new NumNode(_scanner.Number());        _scanner.Accept();    }    //符号变量    else if (token == tIdent)    {        char strSymbol[maxSymLen + 1];        int lenSym = maxSymLen;        //复制symbol到strSymbol        _scanner.GetSymbolName(strSymbol, lenSym);        int id = _symTab.Find(strSymbol);        _scanner.Accept();        //函数调用 如sin(x)        if (_scanner.Token() == tLParen)        {            _scanner.Accept();            pNode = Expr();            if (_scanner.Token() == tRParen)                _scanner.Accept();            else                _status = stError;            if (id != idNotFound && id < _funTab.Size())            {                //函数结点                pNode = new FunNode(_funTab.GetFun(id), pNode);            }            else            {                std::cout << "Unknow function\"";                std::cout << strSymbol << "\"\n";            }        }        else        {            if (id == idNotFound)                id = _symTab.ForcAdd(strSymbol, lenSym);            pNode = new VarNode(id, _store);        }    }    //一元减    else if (token == tMinus)    {        _scanner.Accept();        pNode = new UMinusNode(Factor());    }    else    {        _scanner.Accept();        _status = stError;        pNode = 0;    }    return pNode;}

这里写图片描述
这里写图片描述
这里写图片描述

0 0
原创粉丝点击