程序小白,希望和大家多交流,共同学习
//使用两个栈,一个存储数字,一个存储运算符
//将给定的表达式(没有括号)变成后缀式,然后利用两个栈求出表达式的值
//为方便运算,先给定优先级'#'、'('、'+-'、'*/'、'^'
//所有的
#include<iostream>
#include<math.h>
using namespace std;
struct NodeDigit
{
int data;
NodeDigit *next;
};
typedef NodeDigit *DigitStack;
struct NodeOperator
{
char data;
NodeOperator *next;
};
typedef NodeOperator *OperatorStack;
//充分使用方法重用
//初始化
void init(DigitStack &ds);
void init(OperatorStack &os);
//进栈
void push(DigitStack &ds, int data);
void push(OperatorStack &os, char data);
//出栈
int pop(DigitStack &ds);
char pop(OperatorStack &os);
//判断为空
bool isEmpty(DigitStack ds);
bool isEmpty(OperatorStack os);
//判断满
bool isFull(DigitStack ds);
bool isFull(OperatorStack os);
//得到栈顶
int getTop(DigitStack ds);
char getTop(OperatorStack os);
//放回优先级
int priority(char ch);
//算后缀式,判断左多
int compute(DigitStack &ds, OperatorStack &os);
//锁定输入运算符
bool isOperator(char ch);
int main()
{
DigitStack ds;
OperatorStack os;
init(ds);
init(os);
//错误状况:有空格,除数为零,非法字符输入,连续运算符输入,括号不匹配(左多右多)
push(os, '#');
char ch;
char divide = '#';//记录除号,判断除数是否零
bool op;//记录是否是运算符,判断两次输入是否都是运算符
bool match = true;
while (true)
{
if (!isOperator(ch = getchar()))
{
cout << "非法运算符 " << ch << endl;
break;
}
if (ch == '=')//以'='作为截止符
{
while (getTop(os) != '#')
{
if (getTop(os) == '(')
{
cout << "括号不匹配,左多\n";
break;
}
compute(ds, os);
}
if (getTop(os) != '(')
{
cout << pop(ds) << endl;
}
break;
}
if (ch == '/')//出栈可能会比较慢,直接将除号保存
//由于初始化不是除号,所以下面的判断是对除号后紧接着数字的判断
{
divide = '/';
}
//输入的第一个字符是数字,就将字符推回输入流。
//定义一个整型,用来读取一个完整的数字
if (ch >= '0' && ch <= '9')
{
op = false;
cin.putback(ch);
int digit = 0;
cin >> digit;
if (divide == '/')
{
if (digit == 0)
{
cout << "除数不能为零\n";
break;
}
else
divide = '#';
}
push(ds, digit);
}
else if (ch == '(')
{
push(os, ch);
}
else if (ch == ')')
{
while (getTop(os) != '(')
{
if (getTop(os) == '#')
{
cout << "括号不匹配,右多\n";
match = false;
break;
}
compute(ds, os);
}
if (!match)
{
break;
}
pop(os);//将匹配的(抛出
}
else//不是字符那就是运算符,对于运算符,要么计算,要么入栈
//排除括号的状况
{
if (op && ch != '(' && ch != ')')//先判断,那么判断的就是上一次的op状况
{
cout << "非法输入:连续两次输入运算符 " << ch << endl;
break;
}
op = true;//再赋值,赋值的是这一次的状况
//优先级较高者直接进栈
//否则就计算
//这是一个循环
//最后将新的运算符入栈
while (priority(ch) <= priority(getTop(os)))
{
compute(ds, os);
}
push(os, ch);
}
}
return 0;
}
//初始化
void init(DigitStack &ds)
{
//栈要封底
ds = NULL;
}
void init(OperatorStack &os)
{
os = NULL;
}
//进栈
void push(DigitStack &ds, int data)
{
if (isFull(ds))
{
cout << "数字栈已满,无法进栈\n";
}
else
{
NodeDigit *newNode = new NodeDigit;
newNode -> data = data;
newNode -> next = ds;
ds = newNode;
}
}
void push(OperatorStack &os, char data)
{
if (isFull(os))
{
cout << "运算符栈已满,无法进栈\n";
}
else
{
NodeOperator *newNode = new NodeOperator;
newNode -> data = data;
newNode -> next = os;
os = newNode;
}
}
//出栈
int pop(DigitStack &ds)
{
if (isEmpty(ds))
{
cout << "数字栈已空,无法出栈\n";
return 0;
}
NodeDigit *delosde = ds;
int data = delosde -> data;
ds = ds -> next;
delete delosde;
return data;
}
char pop(OperatorStack &os)
{
if (isEmpty(os))
{
cout << "运算符栈已空,无法出栈\n";
return ' ';
}
NodeOperator *delosde = os;
char data = delosde -> data;
os = os -> next;
delete delosde;
return data;
}
//判断为空
bool isEmpty(DigitStack ds)
{
return ds == NULL;
}
bool isEmpty(OperatorStack os)
{
return os == NULL;
}
//判断满
bool isFull(DigitStack ds)
{
NodeDigit *newNode = new NodeDigit;
if (newNode == NULL)
{
delete newNode;
return true;
}
else
return false;
}
bool isFull(OperatorStack os)
{
NodeOperator *newNode = new NodeOperator;
if (newNode == NULL)
{
delete newNode;
return true;
}
else
return false;
}
//得到栈顶
int getTop(DigitStack ds)
{
if (isEmpty(ds))
{
cout << "数字栈已空,无栈顶数字\n";
return 0;
}
return ds -> data;
}
char getTop(OperatorStack os)
{
if (isEmpty(os))
{
cout << "运算符栈已空,无栈顶运算符\n";
return ' ';
}
return os -> data;
}
//放回优先级
int priority(char ch)
{
switch (ch)
{
case '#':
return 0;
case '(':
return 1;
case '+':
case '-':
return 2;
case '*':
case '/':
return 3;
case '^':
return 4;
}
}
//算后缀式,判断左多
int compute(DigitStack &ds, OperatorStack &os)
{
int d2 = pop(ds);
int d1 = pop(ds);
char op = pop(os);
double result;
switch (op)
{
case '+':
result = d1 + d2; break;
case '-':
result = d1 - d2; break;
case '*':
result = d1 * d2; break;
case '/':
result = d1 / d2; break;
case '^':
result = pow(d1, d2); break;
}
//cout << d1 << op << d2 << "=" << result <<endl;
push(ds, result);
return true;
}
//锁定输入运算符
bool isOperator(char ch)
{
return (ch == '+' || ch == '-' || ch == '*'
|| ch == '/' || ch == '^' || ch == '='
|| (ch >= '0' && ch <= '9') || ch == '('
|| ch == ')');
}
//2+5*6+7*9*10^2+6=
//2+5*6+7/0*10^2+6=
//2+5*6+7*10^2+6
//2+5*6+7**9*10^2+6=
//5*6+(7+8*6)+7^2-5=
//5*6+(7+8*6))+7^2-5=
//5*6+((7+8*6)+7^2-5=
//(5*6+(7+8*6))+7^2-5=