本代码部分思路参照了博主(后面有提及)↓,原链接在下方
数据结构 基于栈的中缀算术表达式求值_fzyz2333的博客-CSDN博客_基于栈的中缀算术表达式求值
博主只是个学生,发个帖子记录下自己的学习心得,这两天不知道为什么自己的Typora崩了几次险些丢失半学期的笔记觉得发到网上或许可以保存的更久。算是自己的学习总结,也不知道写的是不是很冗余,有问题欢迎指出。
不多说了现在进入正题。
本来以为这道题挺简单的,老师也大致讲了下思路,结果我利用课余碎片化的时间做了好久也没做出来,后面心态有点受影响加上很忙没有再去做,眼看着到ddl了,于是今天拿出一早上的时间去写,真的用了整整一早上才解决这一道题。
只能说自己的基础太差了,还是缺少锻炼,感觉代码没有问题但是就是出不来正确的结果,最后一步一步调试才发现了一个一个的问题(第一次用调试,只能说。善于运用调试,真的是太香了)。
问题总结:
1、一开始甚至想将运算符和操作数栈用一个结构体实现,至少在现在的我看来是不能的,这就导致我用 atof 函数转变后虽然得到了正确的浮点型数字,但是却存入了数据类型为char 的OPND栈,而且转化为浮点型的数据也只能存进去一个。
2、函数类型名全起了 int ,导致 return 无法返回正确的数据类型。
3、循环结束条件写的太混乱导致自己也懵了,多次陷入死循环,好在后面调试时理清了思路。
4、到底是用char 还是 string 分不清楚,试了试 atof 函数,发现char * 才管用。而这里参照了上面那位博主的代码使用字符数组,我想atof(数组名)也管用应该是数组名z本身就是个地址,maybe,c语言没好好学(捂脸)。
5、用char 类型的话,对于两位数以上的运算数,怎么把它存放到栈的一个数据中?比如4.5,用char 一个一个输入,先识别到了4,如果压栈,那么0.5怎么办?这里就参照了博主的方法,先把识别到的数字存到到一个字符数组里,一直存到这个数后面的字符是运算符了,那么这个数组里存的内容就是一个运算数了,再进行atof操作,把结果压入OPND栈。
问题基本都是通过“调试”一步一步发现的!再说一遍,调试!真的!太!香!了!!!
总的来说我觉得这一早上挺值得的,确实感觉收获颇丰。
现在附上修改过的原码吧。(BJFU的uu不要直接cv哦,防止查重,有问题我们可以交流!)
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<iomanip>
using namespace std;
#define MAXSIZE 1000
#define OK 1
#define ERROR 0
#define OVERFLOW -2
// 将优先级次序存储到二维数组
char precede[7][7] = {
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=','x',
'>','>','>','>','x','>','>',
'<','<','<','<','<','x','='
};
// 定义用于存放运算符的OPTR栈类型
typedef struct{
char *top;
char *base;
int stacksize;
}SqStack;
// 定义用于存放操作数的OPND栈类型
typedef struct{
double *top;
double *base;
int stacksize;
}SqStackd;
// 对于栈类型的初始化、出栈、入栈、取栈顶操作定义
int InitStack(SqStack &S){
S.base = new char[MAXSIZE];
if(!S.base) exit(OVERFLOW);
S.top = S.base;
S.stacksize = MAXSIZE;
return OK;
}
char Push(SqStack &S,char e){
if(S.top - S.base == S.stacksize) return ERROR;
*S.top++ = e;
return OK;
}
char Pop(SqStack &S){
if(S.top == S.base) return ERROR;
return *--S.top;
}
char GetTop(SqStack S){
if(S.top == S.base) return ERROR;
return *(S.top - 1);
}
int InitStackd(SqStackd &S){
S.base = new double[MAXSIZE];
if(!S.base) exit(OVERFLOW);
S.top = S.base;
S.stacksize = MAXSIZE;
return OK;
}
double Pushd(SqStackd &S,double e){
if(S.top - S.base == S.stacksize) return ERROR;
*S.top++ = e;
return OK;
}
double Popd(SqStackd &S){
if(S.base == S.top) return ERROR;
return *--S.top;
}
double GetTopd(SqStackd S){
if(S.top == S.base) return ERROR;
return *(S.top - 1);
}
// 判断字符是操作数还是运算符
int In(char ch){
switch(ch){
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'=':
return 1;
break;
default:
return 0;
break;
}
}
// 比较优先级,top 栈顶运算符,outside 栈外运算符
char Precede(char top, char outside){
int a,b;
switch(top){
case'+':
a = 0;
break;
case'-':
a = 1;
break;
case'*':
a = 2;
break;
case'/':
a = 3;
break;
case'(':
a = 4;
break;
case')':
a = 5;
break;
case'#':
a = 6;
break;
default: break;
}
switch(outside){
case'+':
b = 0;
break;
case'-':
b = 1;
break;
case'*':
b = 2;
break;
case'/':
b = 3;
break;
case'(':
b = 4;
break;
case')':
b = 5;
break;
case'=':
b = 6;
break;
default: break;
}
return precede[a][b];
}
// 运算求值函数
double operate(double a,char theta,double b){
switch(theta){
case'+':
return a + b;
break;
case'-':
return a - b;
break;
case'*':
return a * b;
break;
case'/':
return a / b;
break;
}
}
// 表达式求值总函数
int EvaluateExpression(SqStack &OPTR,SqStackd &OPND,char *str){
InitStack(OPTR);
InitStackd(OPND);
Push(OPTR,'#');
char ch; // 当前字符
int i = 0; // 用于扫描字符串下标
char z[100] = {}; // 用于暂时存放数字的字符串
int j = 0; // 数字和小数点构成的字符串下标
while(1){
ch = str[i];
if(ch == '\0') break; // 字符串未结束,循环继续
if(In(ch)){ // 运算符
switch(Precede(GetTop(OPTR),ch))
{ // 比较运算符栈顶元素和ch的优先级
case'>':
char theta; // 运算符
double a,b,c; // 运算数a,运算数b,运算结果c
theta = Pop(OPTR);
b = Popd(OPND);
a = Popd(OPND);
c = operate(a,theta,b);
Pushd(OPND,c);
break;
case'<':
Push(OPTR,ch);
i++;
ch = str[i];
break;
case'=':
Pop(OPTR);
i++;
ch = str[i];
break;
default:
i++;
ch = str[i];
break;
}
}
else{
while((ch >= '0' && ch <= '9') || ch == '.'){ // 操作数和小数点,先存进数组再转换为浮点型存入栈
z[j] = ch;
j++;
i++;
ch = str[i];
}
z[j] = 'a'; // 在数组存放数字后加一字母,用于atof函数转化
double d = atof(z);
memset(z,'\0',sizeof(z)); j = 0; // 把数组置空,下标置为0,等待下一个运算数进入
Pushd(OPND,d);
}
}
cout << fixed << setprecision(2) << GetTopd(OPND) << endl;
}
int main(){
char ch = NULL;
char str[MAXSIZE] = {}; // 输入的字符串算术表达式
while(true){
cin >> str; // 输入表达式
ch = str[0]; // 如果输入为等号则结束
if(ch == '=')
break;
else{
SqStack OPTR;
SqStackd OPND;
EvaluateExpression(OPTR,OPND,str);
}
}
return 0;
}