设计模式之解析器(Interpreter)的C++实现

news2024/12/29 9:43:46

1、解析模式的提出

在软件开发的过程中,需要实现一种需求,该需求的结构稳定,但是需求的业务内容会频繁变化,如果使用普通语法实现需求,需要经常更新代码,不具有灵活性。可以使用解析器模式解决实现该类需求,解析器是实现一种能够解析该需求结构语法的功能代码,针对不同的业务调用对应的解析规则代码。

2、需求描述

有一个字符串的加减计算,如'a+b+c-d-e',其中a,b,c,d,e分别对应带计算的值。设计一个功能代码,可以实现该功能,且该代码可以适配不定个数的加减数运算。

3、功能实现

(1)UML图如下:

 (2)代码实现如下:

#include <iostream>
#include <map>
#include <stack>

class AbsExpression
{
public:
    bool isVarType = false;
public:
    void   setExpressionType(bool bFlag){isVarType= bFlag;};
    virtual int interpreter(std::map<char,int>var)=0;
    virtual ~AbsExpression(){};
};

//变量表达式
class ValExpression:public AbsExpression
{
private:
    char m_key;
public:
    ValExpression(const char&key)
    {
        std::cout << "ValExpression " << std::endl;
        this->m_key = key;
        setExpressionType(true);
    }

    int interpreter(std::map<char, int> var) override
    {
        return var[m_key];
    }
    ~ValExpression()
    {
     std::cout << "~ValExpression " << std::endl;
    }
};

//符号表达式
class SymbolExpression:public AbsExpression
{
protected:
    AbsExpression* m_left;
    AbsExpression* m_right;

public:
    SymbolExpression(AbsExpression* left,AbsExpression* right):
        m_left(left),m_right(right)
    {
    }
    ~SymbolExpression()
    {
        //left对象是直接取的栈容器的上一个top,故可以显式清理。
        //right的new对象不会直接push进栈容器,而是做了符号实例对象的成员变量。故需要对其进行对象释放
        if(m_right != nullptr)
        {
            delete m_right;
            m_right = nullptr;
        }
        std::cout << "~SymbolExpression" << std::endl;
    }
};

//加法运算符
class AddExpression:public SymbolExpression
{
public:
    AddExpression(AbsExpression* left,AbsExpression* right):
        SymbolExpression(left,right){
        std::cout << "AddExpression " << std::endl;
    }

    int interpreter(std::map<char,int>var)
    {
        return m_left->interpreter(var) + m_right->interpreter(var);
    }
};
//减法运算符
class SubExpression:public SymbolExpression
{
public:
    SubExpression(AbsExpression* left,AbsExpression* right):
        SymbolExpression(left,right){
        std::cout << "SubExpression " << std::endl;
    }

    int interpreter(std::map<char,int>var)
    {
        return m_left->interpreter(var) - m_right->interpreter(var);
    }
};

std::stack<AbsExpression*> analyse(std::string strLanguage){
    std::stack<AbsExpression*>stackExp;
    AbsExpression* left = nullptr;
    AbsExpression* right = nullptr;

    for(size_t i = 0; i < strLanguage.length();i++)
    {
        switch (strLanguage[i]) {
        case '+':
        {
            left = stackExp.top();
            right = new ValExpression(strLanguage[++i]);
            stackExp.push(new AddExpression(left,right));
        }break;
        case '-':
        {   left = stackExp.top();
            right = new ValExpression(strLanguage[++i]);
            stackExp.push(new SubExpression(left,right));

        }break;
        default:
            stackExp.push(new ValExpression(strLanguage[i]));

        }
    }
    return stackExp;
};

void release( std::stack<AbsExpression*> exp)
{
    while (exp.size() > 0) {
       AbsExpression* it =  exp.top();
       delete it;
       it = nullptr;
       exp.pop();
    }
    std::cout << "clear exp finshed " << std::endl;
}
class Client
{
public:
    void doWork()
    {
        std::string str = "a+b+c-d";
        std::map<char,int>mapVar;
        mapVar.insert(std::make_pair('a',1));
        mapVar.insert(std::make_pair('b',2));
        mapVar.insert(std::make_pair('c',3));
        mapVar.insert(std::make_pair('d',4));
        std::stack<AbsExpression*> exp = analyse(str);
        int ret = exp.top()->interpreter(mapVar);

        std::cout << "ret is " << ret << std::endl;
        release(exp);
    }
};

int main()
{
    Client obj;
    obj.doWork();
    return 0;
}

运行结果如下:

注意:解析器适用于比较简单的语法解析,对于复杂的语法,可以使用语法分析生成器工具,具体的语法分析生成器用法可自行搜索查看。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1021795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

css花字效果

<div data-subtitle"春江潮水连海平" class"colorText">春江潮水连海平</div>.colorText{font-family:ZhanKuKuaiLeTi2016XiuDingBan;font-size: 50px;font-weight: bold;position: relative;background-image: linear-gradient(90deg,#A1B3FB…

同步 -- 自旋锁

基础学习--原子操作 typedef struct {int counter; } atomic_t;static __always_inline void atomic_set(atomic_t *v, int i) {instrument_atomic_write(v, sizeof(*v));raw_atomic_set(v, i); }static __always_inline void raw_atomic_set(atomic_t *v, int i) {arch_atomic…

集丰照明|别墅设计:从空间规划到奢华元素的精心打造

当人们谈论别墅时&#xff0c;总会不自觉地与豪华、舒适、私人空间等词汇联系在一起。确实&#xff0c;别墅作为一种住宅形式&#xff0c;其设计不仅需要满足基本的生活需求&#xff0c;更要有独特的风格和品味。本文将从别墅设计的各个方面进行探讨&#xff0c;带您领略从空间…

uni-app:通过三目运算动态增加样式效果(class)

效果 代码 第一条&#xff1a;当变量line的值等于abc时&#xff0c;class就等于yes,反之class等于no&#xff08;显然等于abc&#xff0c;执行yes,前景色为红色&#xff09; 第一条&#xff1a;当变量line1的值等于abc时&#xff0c;class就等于yes,反之class等于no&#xff…

【实验】H3C校园双出口配置案例,可跟做!

【微|信|公|众|号&#xff1a;厦门微思网络】 1.案例拓补 该拓扑图中的校园网内部分为两个网段&#xff1a;一个为学生校舍网段&#xff08;192.168.2.0&#xff09;&#xff0c;主要访问电信提供的internet服务器&#xff1b;另外一个网段为校园办公和教学用网段&#xff08;…

python 第一次作业

1.使用turtle换一个五环 2.设计这样一个程序&#xff1a;输入一个数字 判断它是不是一个质数 使用turtle换一个五环&#xff1a; >>> import turtle #导入模块 >>> turtle.width(10) #设置圆圈宽度 >>> turtle.color("blue&qu…

DC电源模块具有不同的安装方式和安全规范

BOSHIDA DC电源模块具有不同的安装方式和安全规范 DC电源模块是将低压直流电转换为需要的输出电压的装置。它们广泛应用于各种领域和行业&#xff0c;如通信、医疗、工业、家用电器等。安装DC电源模块应严格按照相关的安全规范进行&#xff0c;以确保其正常运行和安全使用。 D…

快速上手Linux基础开发工具

目录 软件包管理器 概念理解 用法示例 - 以yum为例 vim 模式的切换 常用操作 插件和配置 gcc/g gdb make / makefile 软件包管理器 概念理解 在Linux下安装软件的话&#xff0c;一个比较原始的办法是下载程序的源代码&#xff0c;然后进行编译&#xff0c;进而得到…

vscode 无法使用 compilerPath“D:.../bin/arm-none-eabi-g++.exe”解析配置。

最近在使用vscode搭建ODrive STM32开发环境,依次安装了以下内容: 1.Python3: 用于运行工程构建脚本 2.ST-Link/V2 Drivers: STLink/v2编程器的驱动 3.Visual Studio Code: 轻量级但功能强大的源代码编辑器 …

Python的简单使用与应用

在当今互联网时代&#xff0c;网络爬虫成为了获取数据的重要工具之一。而使用代理IP进行爬虫操作&#xff0c;则是提高爬虫效率、绕过访问限制的利器。本文将向大家介绍Python代理IP爬虫的简单使用&#xff0c;帮助大家了解代理IP的原理、获取代理IP的方法&#xff0c;并探索其…

花了一周时间,更新了下软考云题库Web版

花了一周时间&#xff0c;更新了下软考云题库Web版&#xff0c;体验地址和体验账户在文章最后。想体验的直接翻到最后。 软考云题库的Web版的由来 之前&#xff0c;有朋友提出在小程序中刷题不太方便&#xff0c;希望能在电脑上进行题目练习。于是&#xff0c;我们着手开发了…

AH8316芯片:高效12V转5V 5A电源解决方案

AH8316是一款内置MOS的高效电源转换芯片&#xff0c;具有广泛的应用领域。本文将介绍AH8316芯片的主要特性和性能指标&#xff0c;以及其在12V转5V 5A电源转换中的应用。 AH8316芯片主要特性&#xff1a; 1. 输入电压范围广泛&#xff1a;芯片支持7V至32V的输入电压范围&#…

阿里云无影云电脑角色AliyunServiceRoleForGws什么意思?

阿里云无影云电脑服务关联角色是指角色名称&#xff1a;AliyunServiceRoleForGws&#xff0c;并赋予角色权限策略&#xff1a;AliyunServiceRolePolicyForGws的过程&#xff0c;简单来说&#xff0c;就是允许无影云电脑服务访问您VPC、CEN和NAS中的资源&#xff0c;使用该权限查…

无涯教程-JavaScript - MINVERSE函数

描述 MINVERSE函数返回存储在数组中的矩阵的逆矩阵。 语法 MINVERSE (array)争论 Argument描述Required/OptionalArrayA numeric array with an equal number of rows and columns.Required Notes 数组可以作为单元格范围(如A1:C3)或数组常数(如{1,2,3; 4,5,6; 7,8,9})或这…

Java增强for循环(学习笔记)

Java增强for循环 主要用于数组或者集合的增强型for循环。 格式&#xff1a; for(声明语句&#xff1a;表达式){ 代码句子 } 声明语句&#xff1a;声明新的局部变量&#xff0c;该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块&#xff0c;其值与此时数组元…

Paragon NTFS For Mac2023破解版免费下载安装激活

Paragon NTFS For Mac 2023破解版是一款强大的ntfs磁盘读写工具,帮助用户在MAC电脑上读写NTFS格式的磁盘,需要解决MAC无法读写磁盘的用户可以来试试Paragon磁盘读写软件哦。 Paragon NTFS 2023 专门为解决mac读写开发的软件&#xff0c;它为中国用户量体裁衣&#xff0c;提供Ma…

iText实战--PDF和iText 简介

PDF可以做如下事务 iText 5步创建PDF import java.io.FileOutputStream; import com.itextpdf.text.Document; import com.itextpdf.text.Paragraph; import com.itextpdf.text.pdf.PdfWriter;public class PdfHelloWorld {/*** param args*/public static void main(String[]…

动态内存管理(malloc、free、calloc、realloc函数简介)

动态内存管理 &#x1f383;为什么存在动态内存管理&#x1f383;动态内存函数的介绍&#x1f38a;malloc&#x1f38b;perror函数 &#x1f38a;free&#x1f38a;calloc&#x1f38a;realloc &#x1f383;为什么存在动态内存管理 在此之前&#xff0c;我们开辟内存空间有两种…

shell脚本执行中报错: line 10: 09: value too great for base (error token is “09“)

shell脚本执行中报错&#xff1a; line 10: 09: value too great for base (error token is “09”) 这个错误通常是由于 shell 脚本中对一个数值使用了以零开头的八进制表示方式&#xff0c;而八进制表示中的数字 8 和 9 是无效的引起的。shell 默认将以零开头的数字解释为八进…

【网络安全】你必须知道的几个网络安全概念

一、安全 Web 网关 安全 Web 网关已经从其过去优化互联网带宽的目的演变为保护用户免受来自互联网的恶意内容的侵害。诸如 URL 过滤、反恶意软件、解密和检查通过 HTTPS 访问的网站、数据丢失防护 (DLP) 和云访问安全代理 (CASB) 等功能现已成为标准。 二、 DDoS 防御 DDoS …