题目:基于栈的后缀表达式求值
实验目的:
1.
掌握中缀表达式转换为后缀表达式的算法。
2.
掌握后缀表达式求值的算法。
实验内容:
问题描述
输入一个中缀算术表达式,将其转换为后缀表达式,然后对后缀表达式进行求值。运算符包括:
+
、 -、
*
、
/
、
=
、
(
、
)
,参与运算的为小于
10
的自然数
(
只考虑二元运算即可
)
。
输入要求
多组数据,每组数据一行,对应一个算术表达式,每个表达式均以
“=”
结尾。当表达式只有一个
“=”
时,输入结束。
输出要求
对于每组数据输出
2
行,第
1
行为中缀表达式对应的后缀式,第
2
行为后缀式求值的结果。
输入
样例
9+(3-1)*3+1/2=
1+2=
=
输出样例
931-3*+12/+
15
12+
3
代码
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>//字符分类
#include <string.h>
#define MAX_EXPR_LENGTH 50 // 假设每个表达式的最大长度为50
// 定义栈结构
typedef struct {
int top;//栈顶元素的位置
int* array;//指向整型数组的指针,用于储存栈中元素的数组
} Stack;
// 初始化栈
Stack* createStack(int n) {
Stack* stack = (Stack*)malloc(sizeof(Stack));//动态分配一个存储一个Stack结构体的内存空间,即得到一个指向新分配的栈结构体的指针
stack->top = -1;//初始化栈为空
stack->array = (int*)malloc(n * sizeof(int));//为栈的array成员变量分配足够的内存空间来存储n个整数,即得到一个存储栈中元素的数组
return stack;
}
// 判断栈是否为空
int isEmpty(Stack* stack) {//检测Stack*指针所指向的栈是否为空
return stack->top == -1;//1栈为空, 0栈非空
}
// 获取栈顶元素
int GetTop(Stack* stack) {//获取Stack*指针所指向栈的栈顶元素
return stack->array[stack->top];//tack->array: 这是一个指向整数数组的指针,它存储了栈中的元素。stack->top栈顶元素的位置
}
// 元素入栈
void push(Stack* stack, int item) {
stack->array[++stack->top] = item;//++stack->top使新的值对应栈顶元素的位置,将item放在新的栈顶位置
}
// 元素出栈
int pop(Stack* stack) {
if (!isEmpty(stack)) {//栈不为空
return stack->array[stack->top--];//先返回栈顶元素的值,再使新的stack-top值对应着新的栈顶元素
}
return -1; // 栈为空
}
// 判断字符是否为运算符
int isOperator(char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/';
}
// 获取运算符优先级
int getPriority(char ch) {
switch (ch) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
//中缀表达式转后缀表达式
void infixToPostfix(char* infix, char* postfix) {
Stack* stack = createStack(strlen(infix));//创建一个用于存储运算符和括号的栈,并初始化大小为中缀表达式的长度
// i中缀表达式的字符索引,j后缀表达式的字符索引
for (int i = 0, int j = 0; infix[i]; ++i) {
if (isdigit(infix[i])) {//当前字符是否为数字
postfix[j++] = infix[i];
} else if (infix[i] == '(') {
push(stack, infix[i]);//‘(’ 压入栈中
} else if (infix[i] == ')') {
while (!isEmpty(stack) && GetTop(stack) != '(') {
postfix[j++] = pop(stack);//从stack中弹出元素并添加到后缀表达式字符数组postfix中,直到遇到‘(’,将‘(’弹出,但是并不添加到后缀表达式中
}
pop(stack);
} else if (isOperator(infix[i])) {
//如果栈顶运算符优先级大于等于当前运算符优先级,则从栈stack中弹出元素并添加到后缀表达式字符数组postfix中,直到栈顶运算符优先级小于当前运算符优先级或栈为空。然后将当前运算符压入栈 stack
while (!isEmpty(stack) && getPriority(GetTop(stack)) >= getPriority(infix[i])) {
postfix[j++] = pop(stack);
}
push(stack, infix[i]);
}
}
//在中缀表达式处理完毕后,将栈stack中剩余的所有运算符依次弹出并添加到后缀表达式字符数组postfix中
while (!isEmpty(stack)) {
postfix[j++] = pop(stack);
}
postfix[j] = '\0'; //字符串的结束
free(stack);//释放为stack分配的内存空间
}
// 使用后缀表达式求值
int evaluatePostfix(char* postfix) {
Stack* stack = createStack(strlen(postfix));//创建一个存储数值的栈,初始化大小为后缀表达式的长度
//postfix[i]为NULL时,循环结束
for (int i = 0; postfix[i]; ++i) {
if (isdigit(postfix[i])) {
push(stack, postfix[i] - '0');//把postfix中char转为int存入stack栈中
//对于ASCII编码系统,十进制数字字符(例如 '0'、'1'、'2' 等)的编码值是连续的,它们与对应的整数值相差一个固定的偏移量,即字符 '0' 的ASCII码值。
} else if (isOperator(postfix[i])) {//postfix[i] 是否为运算符。如果是,则从栈 stack 中弹出两个元素作为操作数
int y = pop(stack);//弹出栈顶元素作为第二个操作数
int x = pop(stack);//再弹出栈顶元素作为第一个操作数
switch (postfix[i]) {
case '+':
push(stack, x + y);
break;
case '-':
push(stack, x - y);
break;
case '*':
push(stack, x * y);
break;
case '/':
push(stack, x / y);
break;
}
}
}
return pop(stack);//从栈 stack 中弹出最后一个元素,该元素即为后缀表达式的计算结果。
free(stack);
}
int main() {
int n = 0;
char (*infix)[MAX_EXPR_LENGTH] = NULL;
char (*postfix)[MAX_EXPR_LENGTH] = NULL;
// 动态分配数组空间,初始大小为10
infix = (char(*)[MAX_EXPR_LENGTH])malloc(10 * sizeof(char[MAX_EXPR_LENGTH]));
postfix = (char(*)[MAX_EXPR_LENGTH])malloc(10 * sizeof(char[MAX_EXPR_LENGTH]));
printf("请输入多个中缀表达式(每行一个算术表达式),以单个等号(=)结束输入:\n");
while (1) {
scanf("%s", infix[n]); // 使用scanf函数输入一行字符
if (strlen(infix[n]) == 1 && infix[n][0] == '=') { // 检查字符串长度是否为1且第一个字符是否为等号
break;
}
n++;
}
for (int i = 0; i < n ; i++) {
infixToPostfix(infix[i], postfix[i]);
int result = evaluatePostfix(postfix[i]);
printf("转换成后缀表达式是:%s\t后缀表达式的结果为: %d\n", postfix[i], result);
}
free(infix);
free(postfix);
return 0;
}