1. 实现原理
该计算器数据存储是通过声明一个栈模板,来创建一个 int 类型和 char 类型的栈。int 栈存储表达式中的数字,char 类型的栈存储表达式中的运算符。
在输入表达式时,通过在表达式首尾添加 “#” 来使程序建立表达式的结束条件。当首尾 “#” 相遇时,即表达式已经计算完成,最后输出结果。
当前源代码中只能计算+、-、*、/,以及(),可以将操作数栈改为 double 类型来计算浮点数。
表达式的计算情况处理如下:
- 如果栈顶运算符的优先级低于当前所扫描运算符的优先级,则栈顶的运算符不能计算,故当前扫描的运算符要入栈,然后继续扫描其后续符号。
- 如果栈顶的运算符的优先级高于当前所扫描运算符的优先级,则要取出栈顶运算符进行运算。此时,栈顶运算符的两个操作数一定都在操作数栈的栈顶的两个元素中,取出这两个元素进行运算,并将运算结果再入到此栈中。
- 如果此时的运算符栈不为空,需要继续以栈顶的运算符对当前扫描运算符重复上述比较操作,以此确定是用栈顶运算符运算还是当前扫描运算符入栈。
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. 运行实例
运行截图如下: