【C++】C++顺序栈实现的计算器

1. 实现原理

该计算器数据存储是通过声明一个栈模板,来创建一个 int 类型和 char 类型的栈。int 栈存储表达式中的数字,char 类型的栈存储表达式中的运算符。

在输入表达式时,通过在表达式首尾添加 “#” 来使程序建立表达式的结束条件。当首尾 “#” 相遇时,即表达式已经计算完成,最后输出结果。

当前源代码中只能计算+、-、*、/,以及(),可以将操作数栈改为 double 类型来计算浮点数。

表达式的计算情况处理如下:

  1. 如果栈顶运算符的优先级低于当前所扫描运算符的优先级,则栈顶的运算符不能计算,故当前扫描的运算符要入栈,然后继续扫描其后续符号。
  2. 如果栈顶的运算符的优先级高于当前所扫描运算符的优先级,则要取出栈顶运算符进行运算。此时,栈顶运算符的两个操作数一定都在操作数栈的栈顶的两个元素中,取出这两个元素进行运算,并将运算结果再入到此栈中。
  3. 如果此时的运算符栈不为空,需要继续以栈顶的运算符对当前扫描运算符重复上述比较操作,以此确定是用栈顶运算符运算还是当前扫描运算符入栈。

2. 头文件

头文件源码如下:

#ifndef STACK_H//预处理器  
#define STACK_H  
  
#include <iostream>  
using namespace std;  
  
const int maxlen = 100;//栈的最大存储量  
  
template <typename elementType>  
class stack {  
public:  
    stack();//构造函数,用于初始化(C++11新特性可以在类的声明中初始化变量)  
    bool empty();//判断栈是否为空  
    bool full();//判断栈是否为满  
    bool get_top(elementType &x);//取栈顶元素  
    bool push(elementType x);//元素入栈  
    bool pop();//删除栈顶  
private:  
    int count;//元素的计数器  
    elementType data[maxlen];//顺序存储结构  
};  
  
template <typename elementType>  
stack<elementType>::stack() {  
    count = 0;  
}  
  
template <typename elementType>  
bool stack<elementType>::empty() {  
    if (count == 0)  
        return true;  
    return false;  
}  
  
template <typename elementType>  
bool stack<elementType>::full() {  
    if (count == maxlen)  
        return true;  
    return false;  
}  
  
template <typename elementType>  
bool stack<elementType>::get_top(elementType &x) {  
    if (!empty()) {  
        x = data[count - 1];  
        return true;  
    }  
    return false;  
}  
  
template <typename elementType>  
bool stack<elementType>::push(elementType x) {  
    if (!full()) {  
        data[count++] = x;  
        return true;  
    }  
    return false;  
}  
  
template <typename elementType>  
bool stack<elementType>::pop() {  
    if (!empty()) {  
        --count;  
        return true;  
    }  
    return false;  
}  
  
#endif  

3. 源代码

源代码如下:

#include <iostream>  
#include "stack.h"  
using namespace std;  
  
//扫描数字的函数  
bool isnumber(char x) {  
    if (x >= '0' && x <= '9')  
        return true;  
    return false;  
}  
  
//判断运算符优先级的函数  
int priority(char x) {  
    if (x == '+' || x == '-')  
        return 0;  
    else if (x == '*' || x == '/')  
        return 1;  
    else if (x == '(' || x == ')')  
        return -1;  
    else if (x == '#')  
        return -2;  
}  
  
//运算的函数  
int calculate(string s) {  
    stack<int> number;  
    stack<char> operate;  
    char top;  
    int a, b;  
  
    for (unsigned int i = 0; i < s.size(); ++i) {  
        if (isnumber(s[i])) {  
            int Temp = 0;  
            string temp;  
  
            temp += s[i];  
            while (isnumber(s[++i]))  
                temp += s[i];  
            for (unsigned int j = 0; j < temp.size(); ++j) {  
                Temp = Temp * 10 + temp[j] - 48;  
            }  
            number.push(Temp);  
            temp.clear();  
        }//将字符数字转换成整形数字  
        if (!isnumber(s[i])) {  
            if (operate.empty()) {  
                operate.push(s[i]);  
            }//入栈第一个符号'#'  
            else {  
                operate.get_top(top);  
  
                if (priority(s[i])>priority(top) || s[i] == '(') {  
                    operate.push(s[i]);  
                }//入栈高优先级的运算符  
                else {  
                    while (priority(s[i]) <= priority(top)) {  
                        if (top == '#'&&s[i] == '#') {  
                            int answer;  
  
                            operate.pop();  
                            number.get_top(answer);  
                            cout << "\n答案是:" << answer << endl;  
                            number.pop();  
                            return 0;  
                        }//当运算符实现完全后,只剩下'#'  
                        else if (top == '('&&s[i] == ')') {  
                            ++i;  
                        }//当左右括号相遇时,跳过右括号,删除左括号  
                        else {  
                            number.get_top(a);  
                            number.pop();  
                            number.get_top(b);  
                            number.pop();  
                        }  
                        if (top == '+') {  
                            b += a;  
                            number.push(b);  
                        }  
                        else if (top == '-') {  
                            b -= a;  
                            number.push(b);  
                        }  
                        else if (top == '*') {  
                            b *= a;  
                            number.push(b);  
                        }  
                        else if (top == '/') {  
                            b /= a;  
                            number.push(b);  
                        }  
                        operate.pop();  
                        operate.get_top(top);//取前一个运算符,用于与现在扫描的运算符进行比较    
                    }//将优先级高的运算符实现计算  
                    operate.push(s[i]);//用于当top=='#'时,将最后一个运算符入栈  
                }  
            }  
        }//扫描运算符,并判断优先级,以及运算  
    }//主循环  
}//对运算符的扫描,和数字字符的转化,以及计算  
  
int main() {  
    string expression;  
    cout << "输入一个用'#'开头和结尾的表达式:" << endl;  
    cin >> expression;  
    calculate(expression);  
    cin.get(), cin.get();  
}  

4. 运行实例

运行截图如下:

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值