基于C++实现带parser功能的计算器

前一阵子复习STL的时候,结合轮子哥的教程做了一下基于Stack的带parser功能的计算器。具体功能就是输入带括号的四则运算,比如”(1+2)*3+2”,程序可以自动parser,并得出最后的结果为11。

现在直接贴代码,具体的注释都在里面~
calculator_parser的github地址

#include <iostream>
#include <string>
#include <stack>
#include <sstream>

using namespace std;

// 基于Stack构建计算器(带括号等等)
// ① Item类 存储数据和操作符
// ② 出入Push和Pop函数
// ③ Calculate函数——里面有一个Stack<Item>的堆和 stringstream,用于分析每个字符形式
// ④ Run函数——实现具体计算

struct Item {
    int number = 0;
    char op = '\0';

    // 默认的构造函数
    Item() {}
    Item(char operators): op{operators} {}
};


// Run返回的栈顶的最上面两个元素的和,保存在第二高的栈顶元素上。并把最高的栈顶元素出栈。
void Run(stack<Item>& items)
{
    auto second = items.top();
    items.pop();
    auto& first = items.top().number;
    switch (second.op)
    {
    case '+':
        first += second.number;
        break;
    case '-':
        first -= second.number;
        break;
    case '*':
        first *= second.number;
        break;
    case '/':
        first /= second.number;
        break;
    }
}

void Push(stack<Item>& items, int number) {

    items.top().number = number;
    switch (items.top().op)
    {
    // 只要运算符为*或者/,都执行Run(items)
    case '*':case '/':
        Run(items);
    }

}

int Pop(stack<Item>& items)
{
    while (items.top().op != '\0')
    {
    // 根据Run可以看出,真正实现出栈操作的stack.pop()是在
    // Run函数里面完成的。
        Run(items);
    }
    /*4*/
    // pop()没有返回值
    auto number = items.top().number;
    items.pop();
    return number;
}

int Calculate(string text)
{
    stringstream ss(text);
    stack<Item> items;
    // 栈初始化的时候,就往里面添加一个item
    items.push({});

    while (true)
    {
        // ss.peek 查看下一字符,但不提取
        char op = ss.peek();
        switch (op)
        {
        case '(':
            // 相当于items.push(Item {});
            items.push({});
            break;
        case ')':
            Push(items, Pop(items));
            break;
        case '+':case '-':case '*':case '/':
            items.push({op});
            break;
        }

        if (isdigit(op))
        {
            int number;
            ss >> number;
            Push(items, number);
        }
        else if (ss.eof())
        // 到头了——>string stream到达末尾
        {
            return Pop(items);
        }
        else
        {
            ss.ignore();
        }
    }
}


int main() {
    auto item = Calculate("(1+2)*3+2");
    cout << item << endl;
    // 输出的应该为11

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值