任务
1、实现堆栈,包括堆栈的生成,压栈,出栈操作
2、用户输入表达式,使用堆栈对表达式进行求解并且输出结果
总体思路
定义储存数据的栈
定义两个类,一个储存的数据是 float 类型,一个储存的是 char 类型。即可实现将数字储存成 float 类型,而不是 ASCII 码,假如将数字储存成 ASCII 码,只能输入个位数,后续运算中也不能出现太大的数字,否则会储存失败。
#include <iostream>
using namespace std;
class number {
public:
float data;
number* next;
};
class operate {
public:
char data;
operate* next;
};
定义压栈出栈函数
因为定义了两个类型的栈,所以压栈出栈函数要定义两份,一份用来操作数字栈,一份用来操作符号栈。
特别注意的是压数字栈函数,只要压入一个数字,则计数加 1,只要压入数字前计数不为 0,则 pop一个数字出来,乘上 10 后加上准备入栈的数字,赋值给准备入栈的数字再入栈。
void pushnumber(number*&stack1,float a,int &jishu) {
int result = 0;
if (jishu == 0) {
number* node1 = NULL;
node1 = new number;
node1->data = a;
node1->next = stack1;
stack1 = node1;
jishu++;
}
else
{
result = (stack1->data) * 10 + a;
stack1->data = result;
}
}
void pushoperate(operate*& stack2, char a) {
operate* node2 = NULL;
node2 = new operate;
node2->data = a;
node2->next = stack2;
stack2 = node2;
}
void popnumber(number*&stack1,float& a) {
a = stack1->data;
stack1 = stack1->next;
}
void popoperate(operate*& stack2, char& a) {
a = stack2->data;
stack2 = stack2->next;
}
定义比较符号优先级的函数
根据符号优先级表建立一个二维 7×7 矩阵,然后再定义一个函数用来确定两个要比较的符号分别是什么,在二维表中找到优先级。
int check(char a) {
if (a == '+') {
return 0;
}
if (a == '-') {
return 1;
}
if (a == '*') {
return 2;
}
if (a == '/') {
return 3;
}
if (a == '(') {
return 4;
}
if (a == ')') {
return 5;
}
if (a == '#') {
return 6;
}
}
int pk(operate*stack2,char a) {//pk两个操作符优先级
int x[7][7] = { -1,-1,1,1,1,-1,-1,
-1,-1,1,1,1,-1,-1,
-1,-1,-1,-1,1,-1,-1,
-1,-1,-1,-1,1,-1,-1 ,
1,1,1,1,1,0,2,
-1,-1,-1,-1,2,-1,-1,
1,1,1,1,1,2,0};//1表示大于,0表示相等,-1表示小于,2表示表达式错误
return x[check(stack2->data)][check(a)];
}
主函数
cin 表达式储存进数组,然后一项一项操作,只要是符号就调用压符号栈函数,其他的都调用压数字栈函数。 并且只要确定正在操作的这项是符号,则立刻重置计数为 0。并且需要注意的是,当发生压符号栈时优先级小于栈顶的符号的优先级,应该将 for 循环计数减 1,即再次尝试压栈。
int main() {
cout << "请输入要求解的表达式:(小数改为分数表示,且表达式以#结尾)" << endl;
char a[500]{}; int length = 0; int jishu = 0;
for (int i = 0; i < 500; i++) {//将表达式输入进数组
cin >> a[i];
length++;
if (a[i] == '#') {//如果遇到#则停止输入
break;
}
}
number* numbernode = NULL; operate* operatenode = NULL;
pushoperate(operatenode, '#');//先把一个#压进操作符栈
for (int i = 0; i < length; i++) {
if (a[i] == '+' || a[i] == '-' || a[i] == '*' || a[i] == '/' || a[i] == '(' ||
a[i] == ')' || a[i] == '#') {//如果为操作符
jishu = 0;
int x = pk(operatenode, a[i]);//优先级比较的结果放进x
if (x == 2) {//如果优先级比较出错,则断开
break;
}
if (x==1) {//如果“要压的操作符的优先级”大于“栈顶操作符的优先级”,则正常压栈
pushoperate(operatenode, a[i]);
}
if (x == -1) {//如果“要压的操作符的优先级”小于“栈顶操作符的优先级”,则:
float a1 = 0; float a2 = 0;//储存要运算的两个数据
char a3;//储存运算符
popnumber(numbernode, a1);
popnumber(numbernode, a2);
popoperate(operatenode, a3);
if (a3 == '+') {
pushnumber(numbernode, a2 + a1,jishu);
}
if (a3 == '-') {
pushnumber(numbernode, a2 - a1,jishu);
}
if (a3 == '*') {
pushnumber(numbernode, a2 * a1,jishu);
}
if (a3 == '/') {
pushnumber(numbernode, a2 / a1,jishu);
}
i--;
}
if (x == 0) {//如果')'遇到'(',则抵消
char a3;
popoperate(operatenode, a3);
}
}
else//除了符号,全都进数字栈
{
pushnumber(numbernode, a[i]-'0', jishu);
}
}
cout << "最终结果为:" << numbernode->data;
}