利用顺序栈,实现+、-、*、/、%运算,支持括号输入,可输入负数,暂不支持小数(也许不久的以后就实现了)。
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
/*定义顺序栈*/
template <class T>
class ArrayStack {
private:
T *stack;
int stacksize;
int stacktop;
public:
ArrayStack(int size) {
stacksize = size;
stack = new T[stacksize];
stacktop = -1;
}
bool isEmpty() {
if (stacktop == -1) return true;
return false;
}
T Top() {
return stack[stacktop];
}
void Pop() {
if (stacktop == -1) {
cout << "the stack is empty,please check your input." << endl;
exit(100); //直接终止程序
}
stacktop--;
}
void Push(const T& val) {
stack[++stacktop] = val;
}
};
/*栈内优先级*/
int In(char a) {
switch (a) {
case '#':
return 0;
case '(':
return 1;
case '*':
case '/':
case '%':
return 5;
case '+':
case '-':
return 3;
case ')':
return 8;
default:
cout << "please check your expression" << endl;
exit(400);
}
}
/*栈外优先级*/
int Out(char a) {
switch (a) {
case '#':
return 0;
case '(':
return 8;
case '*':
case '/':
case '%':
return 4;
case '+':
case '-':
return 2;
case ')':
return 1;
default:
cout << "please check your expression" << endl;
exit(300);
}
}
/*运算*/
int Caculate(int num1, int num2, char a) {
switch (a) {
case '*':
return (num1 * num2);
case '/':
if (num2 == 0) {
cout << "the divisor is not 0" << endl;
exit(500);
}
else {
return (num1 / num2);
}
case '%':
if (num2 == 0) {
cout << "the divisor is not 0" << endl;
exit(500);
}
else {
return (num1 % num2);
}
case '+':
return (num1 + num2);
case '-':
return (num1 - num2);
default:
cout << "please check your expression" << endl;
exit(200);
}
}
/*检查输入是否合法且检查括号是否匹配*/
bool Check(char *expression, int length) {
ArrayStack<char> a(length);
/*防止直接输入两个'#'*/
if (length <= 2) {
cout << "please check your expression" << endl;
return false;
}
/*检查是否具有首尾标志*/
if (expression[0] != '#'|| expression[length-1] != '#') {
cout << "please start and end with '#'" << endl;
return false;
}
int i;
/*检查括号是否匹配*/
for ( i = 1; i<length; i++) {
if (expression[i]=='(') {
a.Push(expression[i]);
}else if (expression[i]==')') {
if (!a.isEmpty())
a.Pop();
else if(a.isEmpty()) {
cout << "please check your expression" << endl;
return false;
}
}
}
if (!a.isEmpty()) {
cout << "please check your expression" << endl;
return false;
}
return true;
}
/*负数处理,将负数变为“0-x”的形式*/
void Format(string &s) {
int i;
for (i = 0; s[i] != '\0'; i++) {
if (i == 1 && s[i] == '-') {
s.insert(i, "0", 1);
}
else if(s[i] == '-'&&s[i - 1] == '(') {
s.insert(i, "0", 1);
}
}
}
/*具体操作*/
void Caculator(ArrayStack<int> &numstack, ArrayStack<char> &opstack,string &expression) {
int i, val = 0;
int num1, num2; //num1为被减数或被除数
opstack.Push(expression[0]); //将开始位放入符号栈
for (i = 1; expression[i]; i++) { //首位以入栈,从第二位开始
/*数字入栈操作*/
if (expression[i] >= '0'&&expression[i] <= '9') {
while (expression[i] >= '0'&&expression[i] <= '9') {
val = 10 * val + (expression[i] - '0');
i++;
}
numstack.Push(val);
val = 0; //给val清零
i--; //i退位
}
else {
/*运算符优先级比较*/
//栈内优先级低于栈外优先级,则站外运算符进栈
if (Out(expression[i]) > In(opstack.Top())) {
opstack.Push(expression[i]);
}
//栈外优先级低于栈内优先级,则栈内运算符进行计算
else if (Out(expression[i]) < In(opstack.Top()))
{
for (; Out(expression[i]) < In(opstack.Top());) { //一直运算直到栈内优先级低于栈外优先级
num2 = numstack.Top();
numstack.Pop();
num1 = numstack.Top(); //num1为被减数或被除数
numstack.Pop();
numstack.Push(Caculate(num1, num2, opstack.Top()));
opstack.Pop(); //运算结束,栈顶运算符出栈
}
if (Out(expression[i]) == In(opstack.Top()))
opstack.Pop();
else if (Out(expression[i]) > In(opstack.Top()))
opstack.Push(expression[i]);
}
/*栈内优先级等于栈外优先级,栈顶运算符出栈*/
else if (Out(expression[i]) == In(opstack.Top()))
{
opstack.Pop();
}
}
}
}
int main() {
string expression;
int flag;
int val = 0; //用于将char型数字字符转换为int型
cout << "Input your expression,start with '#' and end with '#':" << endl;
cout << "If there are negative numbers, Please Enclose in parentheses.eg:#2+(-1)#" << endl;
input:
cin >> expression ;
int length = expression.length();
if (!Check(&expression[0], length)) {
goto input;
}
Format(expression); //字符串处理
ArrayStack<int> numstack(length); //数字栈
ArrayStack<char> opstack(length); //符号栈
Caculator(numstack, opstack, expression); //实现计算器
cout << "the result is:" << numstack.Top() << endl;
cout << "enter 1 to continue,enter 0 to end" << endl;
cin >> flag;
if (flag == 1)
goto input;
else
return 0;
}
主要凭借栈内外运算符优先级不同实现,具体如下:
1.栈内优先级低于栈外优先级,则站外运算符进栈
2.栈外优先级低于栈内优先级,则栈内运算符进行计算
3.栈内优先级等于栈外优先级,栈顶运算符出栈
运算符及相应优先级:
# | +、- | *、/、% | ( | ) | |
栈内 | 0 | 3 | 5 | 1 | 8 |
栈外 | 0 | 2 | 4 | 8 | 1 |
/*本人较菜,代码还有许多能改进的地方,有什么建议或问题麻烦一定指出,评论区欢迎留言!*/
/*要看链式栈计算器请移步我好兄弟的帖子*/ /*【数据结构学习】利用链式栈实现中缀表达式的简易计算器_鹭雨君Loorain的博客-CSDN博客*/
更:
改进了对负数的处理,把-x写成0-x的形式
/*负数处理,将负数变为“0-x”的形式*/
string Format(string s) {
int i;
for (i = 0; s[i] != '\0'; i++) {
if (i == 1 && s[i] == '-') {
s.insert(i, "0", 1);
}
else if(s[i] == '-'&&s[i - 1] == '(') {
s.insert(i, "0", 1);
}
}
return s;
}
增加了结束后输入1开始下一次计算,输入0结束的功能。
取消了字符判断(我是真的蠢才写字符判断),简化了主函数,增加了一些边界检查。
之前的大段代码已经修改了。