一.实验目的
1.理解栈的结构特点和基本操作特性;
2.掌握利用栈实现表达式求值算法。
二.实验内容
输入一个算术表达式(以“=”结束),求其值。要求表达式以“=”结束,操作数为多位实数,对错误表达式要进行检测。
1.设置两个栈:optr算符栈和opnd操作数栈。初始置opnd为空栈;起始符“=”为optr的栈底元素;
2.自左向右扫描表达式中的每个字符c:
1)若c为操作数,则进opnd栈;
2)若c为算符,则让optr栈的栈顶元素与c比较优先级:
a.若栈顶算符优先级低于刚读入的运算符c,则让刚读入的运算符c进optr栈。
b.若栈顶算符优先级高于刚读入的运算符c,则将栈顶算符退栈,送入q;同时将操作数栈opnd退栈两次,得到两个操作数b、a,对a、b进行aqb运算后,将运算结果作为中间结果推入opnd栈。
c.若栈顶运算符的优先级与刚读入的运算符c相同,说明左右括号相遇,只需将栈顶运算符(左括号)退栈即可。
3.直到扫描到c为定界符,即optr栈的栈顶元素和当前读入的字符均为“=”,则整个表达式求值完毕。
三.代码
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
#define MAXSIZE 100
#define ERROR -1
typedef double DataType; // 将 DataType 改为 double 以处理浮点数
typedef struct{
DataType data[MAXSIZE];
int top;
}SqStack;
// 构建一个空栈
int InitStack(SqStack &S){
S.top = -1;
return true;
}
// 判断栈是否为空
int StackEmpty(SqStack S){
return (S.top == -1? true:false);
}
// 判断栈是否满了
int StackFull(SqStack S){
return (S.top == MAXSIZE-1? true:false);
}
// 进栈
int Push(SqStack &S, DataType e){
if (StackFull(S)) return ERROR;
S.top++;
S.data[S.top] = e;
return true;
}
// 出栈
int Pop(SqStack &S, DataType &e){
if(StackEmpty(S)) return ERROR;
e = S.data[S.top];
S.top--;
return true;
}
DataType GetTop(SqStack S){
// 若栈不为空,则取栈顶元素
DataType e;
if(StackEmpty(S)) return ERROR; // 栈空
e=S.data[S.top]; // 取出数据,top 不变
return e;
}
/* 比较两个运算符的优先级 */
char Precede (char a, char b){
char z;
if ((b == '+')||(b == '-')||(b == '*')||(b == '/')||(b == '(')||(b == ')')||(b == '=')){
switch(a){
case '+':
case '-':
if ((b =='*')||(b == '/')||(b == '(')) z = '<';
else z = '>';
break;
case '*':
case '/':
if (b == '(') z = '<';
else z = '>';
break;
case '(':
if (b == '=') z = 'E';
else
if (b ==')') z = '=';
else z = '<';
break;
case ')':
if (b == '(') z = 'E';
else z = '>';
break;
case '=':
if (b == '=') z = '=';
else
if (b == ')') z = 'E';
else z = '<';
break;
}
}else z = 'E';
return (z);
}
/* 判断字符 ch 是否为算符 */
int In(char ch){
int i, flag = 0;
char op[7] = {'+', '-', '*', '/', '(', ')', '='};
for (i = 0; i < 7 ; i ++ )
if (ch == op[i]){
flag = 1;
break;
}
return flag;
}
DataType Operate(DataType a, char theta, DataType b){
DataType z;
switch(theta){
case '+': z = a + b; break;
case '-': z = a - b; break;
case '*': z = a * b; break;
case '/': z = a / b; break;
}
return (z);
}
double CaculateExpression(){
// 算法表达式求值的算符优先算法。设 optr 和 opnd 分别为算符栈和操作数栈
// OP 为算符集合
SqStack optr, opnd;
double x, theta, a, b, sum, count;
char c;
c = getchar();
InitStack(optr);
Push(optr, (int)'=');
InitStack(opnd);
while (c!= '=' || GetTop(optr)!= '='){
if (In(c)){ // 如果是运算符
switch(Precede(GetTop(optr), c)){
case '<': // 栈顶算符优先级低
Push(optr, c); c = getchar();
break;
case '=': // 优先级相同, 脱去括号病读入下一个字符
Pop(optr, x); c = getchar();
break;
case '>': // 栈顶算符优先级高, 退栈并将运算结果入栈
Pop(optr, theta);
Pop(opnd, b); Pop(opnd, a);
Push(opnd, Operate(a, theta, b));
break;
}
} else { // 如果是数字
double num = 0;
while (c >= '0' && c <= '9'){ // 连续读取数字字符
num = num * 10 + c - '0';
c = getchar();
if (c == '.')
{
count ++;
c = getchar();
}
}
num = num / pow(10, count);
Push(opnd, num); // 将数字入操作数栈
count = 0;
}
}
return GetTop(opnd);
}
int main(){
printf("%lf",CaculateExpression()); // 将输出格式改为 %f 以输出浮点数
return 0;
}
欢迎订阅专栏,数据结构实验,期末大作业,前端后端都有哦,想我发哪个方面的资源或文章可以私信我,免费的哦