博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ Programming Language中的Calculator源代码
阅读量:4678 次
发布时间:2019-06-09

本文共 6160 字,大约阅读时间需要 20 分钟。

C++ Programming Language 4th中的Calculator源代码整理,因为在C++ Programming Language中,涉及了很多文件位置之类的变化,所以,这里只是其中的一个版本:

error.h

#include 
#include
namespace Error{ extern int no_of_errors; inline double error(const std::string& s) { no_of_errors++; std::cerr << "error:" << s << '\n'; return 1; }}

Table.h

#include #include 
namespace Table{ extern std::map
table;}

Lexer.h

#include 
#include
namespace Lexer{ enum class Kind : char { name, number, end, plus='+', minus='-', mul='*', div='/', print=';', assign='=', lp='(', rp=')' }; struct Token { Kind kind; std::string string_value; double number_value; }; class Token_stream { public: Token_stream(std::istream& s) : ip{&s}, owns(false) { } Token_stream(std::istream* p) : ip(p), owns{ true } { } ~Token_stream() { close(); } Token get(); // read and return next token Token& current() // most recent read token { return ct; } void set_input(std::istream& s) { close(); ip = &s; owns = false; } void set_input(std::istream* p) { close(); ip = p; owns = true; } private: void close() { if (owns) delete ip; } std::istream* ip; // pointer to an input stream bool owns; // does the Token_stream own the istream? Token ct{ Kind::end }; // current token }; extern Token_stream ts;}

Parser.h

namespace Parser{    double prim(bool get);    double term(bool get);    double expr(bool get);}

Driver.h

#include 
#include "Lexer.h"#include "Parser.h"namespace Driver{ using namespace Lexer; using namespace Parser; inline void calculate() { for (;;) { ts.get(); if (ts.current().kind == Kind::end) break; if (ts.current().kind == Kind::print) continue; std::cout << expr(false) << "\n"; } }}

Error.cpp

#include "Error.h"namespace Error{    int no_of_errors = 0;}

Table.cpp

#include "Table.h"namespace Table{    std::map
table;}

Lexer.cpp

#include "Lexer.h"#include 
namespace Lexer{ Token Token_stream::get() { char ch = 0; do { // skip whitespace except '\n' if (!ip->get(ch)) return ct = { Kind::end }; } while (ch != '\n' && isspace(ch)); switch (ch) { case 0: return ct = { Kind::end }; // assign and return case ';': // end of expression; print case '\n': return ct = { Kind::print }; case '*': case '/': case '+': case '-': case '(': case ')': case '=': return ct = {static_cast
(ch)}; case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': case '.': ip->putback(ch); // put the first digit (or .) back into the input stream *ip >> ct.number_value; // read number into ct ct.kind = Kind::number; return ct; default: // name, name = , or error if (isalpha(ch)) { ct.string_value = ch; while (ip->get(ch) && isalnum(ch)) ct.string_value += ch; // append ch to end of string_value ip->putback(ch); return ct = { Kind::name }; } } } Token_stream ts{ std::cin };}

Parser.cpp

#include "Parser.h"#include "Lexer.h"#include "Error.h"#include "Table.h"namespace Parser{    using namespace Lexer;    using namespace Error;    using namespace Table;    double expr(bool get)        // add and subtract    {        double left = term(get);        for (;;)        {            switch (ts.current().kind)            {            case Kind::plus:                left += term(true);                break;            case Kind::minus:                left -= term(true);                break;            default:                return left;            }        }    }            double term(bool get)        // multiply and divide    {        double left = prim(get);        for (;;)        {            switch (ts.current().kind)            {            case Kind::mul:                left *= prim(true);                break;            case Kind::div:                if (auto d = prim(true))                {                    left /= d;                    break;                }                return error("divide by 0");            default:                return left;            }        }    }    double prim(bool get)        // handle primaries    {        if (get) ts.get();        // read next token        switch (ts.current().kind)        {        case Kind::number:            // floating-point constant        {            double v = ts.current().number_value;            ts.get();            return v;        }        case Kind::name:        {            double& v = table[Lexer::ts.current().string_value];        // find the corresponding            if (ts.get().kind == Kind::assign)                v = expr(true);                                        // '=' seen: assignment            return v;        }        case Kind::minus:        // unary minus            return -prim(true);        case Kind::lp:        {            auto e = expr(true);            if (ts.current().kind != Kind::rp)                return error("')' expected");            ts.get();        // eat ')'            return e;        }        default:            return error("primary expected");        }    }}

实际使用代码(测试代码):

#include "Error.h"#include "Driver.h"#include "Table.h"int main(){    Table::table["pi"] = 3.1415926535897932385; // inser t predefined names    Table::table["e"] = 2.7182818284590452354;    Driver::calculate();    return Error::no_of_errors;}

 

转载于:https://www.cnblogs.com/albizzia/p/8997953.html

你可能感兴趣的文章
oracle 有哪些字典表,oracle 常用字典表
查看>>
linux c多进程多线程,linux下的C\C++多进程多线程编程简易例子
查看>>
linux 命令 考试,linux常用命令总结-第一次考试
查看>>
linux动态库编译多重依赖,Linux动态库多重依赖
查看>>
linux网卡缓冲区设置,【Linux】tcp缓冲区大小的默认值、最大值
查看>>
opus编译linux,Linux 下源码编译FFMEG
查看>>
linux 运行real basic,REALbasic 快速入门.pdf
查看>>
linux启动tomcat不停的触发gc,tomcat启动时就频繁gc和full gc
查看>>
linux uart串口驱动,X-017-KERNEL-串口驱动开发之uart driver框架
查看>>
linux 添加串口数量,如何在Linux中添加4个以上的串口设备?
查看>>
SCUT - 482 - 生成树上的点 - Prufer
查看>>
SCUT - G - 魔法项链 - 树状数组
查看>>
洛谷 - P1462 - 通往奥格瑞玛的道路 - 二分 - Dijkstra
查看>>
洛谷 - P1346 - 电车 - Dijkstra/01BFS
查看>>
洛谷 - P1522 - 牛的旅行 - Cow Tours - Floyd
查看>>
模板 - Prim
查看>>
模板 - Floyd
查看>>
模板 - 强连通缩点
查看>>
模板 - 强连通分量 - Kosaraju
查看>>
Codeforces - 1203D2 - Remove the Substring (hard version) - 双指针
查看>>