逆波兰表达式的计算通常采用栈实现,这里我们使用链栈,逆波兰表达式用字符数组存储,实现起来也是很简单的,我们依次遍历逆波兰表达式的每一个字符,当遇到数字就入栈,否则就进行计算,计算之前先从栈中取出两个数字,进行四则运算,计算完成后结果入栈。在C语言中整形和字符型的转换有个很巧妙的技巧,但数值计算结果要求在0-9之间,否则转换时没有对应的ASCII值便会出错,我们在下面四则运算时将会使用到!当然你也可以用一些标准库函数atoi,atol,atof函数这些进行转换,可以完成其他绝大部分计算(受计算机精度影响)。
例如:'5'转5,5转'5'
char转int '5'-'0'=5
int转char 5+'0'='5'
原理:
1.两个char型相减得到的是他们的差值,这个差值正好是整型因为C语言使用的是字符对应的ASCII值进行计算,我们减字符'0'正好得到的是该字符对应的整型数值
2.一个int型与一个char型相加,运算结果为char型的ASCII值+int型的数值(这里整型用的是它自己的数值大小没有使用整型的ASCII值进行运算)计算出来的ASCII值正好对应结果的数字字符
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Status int
#define OK 1
#define Error 0
#define OVERFLOW 1
// 定义栈的结构体
typedef struct Stack {
char Element; // 栈元素
struct Stack* next; // 指向下一个栈元素的指针
} Stack;
// 初始化栈
Status InitStack(Stack* Head) {
Head = (Stack*)malloc(sizeof(Stack)); // 分配内存给栈头节点
if (!Head) exit(OVERFLOW); // 如果内存分配失败,退出程序
Head->next = NULL; // 初始化栈为空
return OK;
}
// 获取栈顶元素
Status GetTop(Stack Head, char* e) {
if (!Head.next) return Error; // 如果栈为空,返回错误
*e = Head.next->Element; // 获取栈顶元素
return OK;
}
// 入栈操作
Status Push(Stack* Head, char e) {
if (!Head) return Error; // 如果栈头指针无效,返回错误
Stack* p = (Stack*)malloc(sizeof(Stack)); // 分配内存给新栈元素
if (!p) return OVERFLOW; // 如果内存分配失败,返回溢出
p->Element = e; // 设置栈元素值
p->next = Head->next; // 将新节点的 next 指针指向原栈顶
Head->next = p; // 更新栈头指针的 next 指向新节点
return OK;
}
// 出栈操作
Status Pop(Stack* Head) {
if (!Head) return Error; // 如果栈头指针无效,返回错误
if (!Head->next) return Error; // 如果栈为空,返回错误
Stack* p = Head->next; // 获取栈顶元素
Head->next = p->next; // 更新栈头指针的 next 指向原栈顶的下一个元素
free(p); // 释放栈顶元素的内存
return OK;
}
int main() {
Stack stack; // 创建栈实例
InitStack(&stack); // 初始化栈
char str[] = { '5', '2', '-', '4', '*', '\0' }; // 逆波兰表达式,原始中缀表达式为:(5-2)*4
// 遍历逆波兰表达式
for (int i = 0; i < strlen(str); i++) {
// 如果遇到运算符
if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
char num1, num2;
GetTop(stack, &num1); // 获取栈顶元素
Pop(&stack); // 出栈
GetTop(stack, &num2); // 获取新的栈顶元素
Pop(&stack); // 出栈
// 执行相应的运算,并将结果入栈
if (str[i] == '+') Push(&stack, ((num2 - '0') + (num1 - '0')) + '0');
if (str[i] == '-') Push(&stack, ((num2 - '0') - (num1 - '0')) + '0');
if (str[i] == '*') Push(&stack, ((num2 - '0') * (num1 - '0')) + '0');
if (str[i] == '/') Push(&stack, ((num2 - '0') / (num1 - '0')) + '0');
}
else {
Push(&stack, str[i]); // 如果是数字,则直接入栈
}
}
char result;
GetTop(stack, &result); // 获取最终计算结果
Pop(&stack); // 出栈结果
// 打印逆波兰式
printf("逆波兰式为: ");
for (int i = 0; i < strlen(str); i++) {
printf("%c", str[i]);
}
printf("\n计算的结果为: %d\n", result - '0'); // 打印计算结果
return 0;
}
运行结果: