一般的后缀表达式(也叫逆波兰表达式),要想计算这样的表达式,可以利用到栈。
1.栈的逻辑和1.栈 博客是一样的
2.计算方法及代码
2.1先接受输入一个字符,在while循环判断结束标志 ‘#’,在循环中继续接受输入下一个字符
2.1 对数字字符和计算符号字符分别的处理。
对于计算符号,用switch 分别对+-*/ 进行分类,遇到输入的字符是计算符号, 先将两个栈的数据pop出栈,将出栈的两个数据,进行+-*/的计算
对于数字字符,用isdigit函数判断字符是否是数字,或者字符是否带小数点。因此我们设置了一个字符数组缓冲区str[MAXBUFFER],用来接收数字字符。之后将str[MAXBUFFER]用atof函数转换为double类型的数据,将该double类型的数据push入栈
// 栈-后缀表达式.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS //为了避免scanf函数报错
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#define InitSize 20
#define IncrementSize 10
#define MAXBUFFER 10
typedef double ElimentType;
typedef struct
{
ElimentType* top;
ElimentType* base;
int StackSize;
}sqStack;
void InitStack(sqStack* s)
{
s->base = (ElimentType*)malloc(InitSize * sizeof(ElimentType));
if (!s->base)
{
exit(0);
}
s->top = s->base;
s->StackSize = InitSize;
}void Push(sqStack* s, ElimentType c)
{
if (s->top - s->base >= s->StackSize)
{
s->base = (ElimentType*)realloc(s->base, (s->StackSize + IncrementSize) * sizeof(ElimentType));
if (!s->base)
{
exit(0);
}
s->top = s->base + s->StackSize;
s->StackSize = s->StackSize + IncrementSize;
}
*(s->top) = c;
s->top++;
}
void Pop(sqStack* s, ElimentType* c)
{
if (s->top == s->base)
{
return;
}
s->top--;
*c = *(s->top);
}
int Stacklen(sqStack s)
{
int len = 0;
len = s.top - s.base;
return len;
}
int main()
{
sqStack s;
InitStack(&s);
char c, d;
double e,f,g;
char str[MAXBUFFER];
int t=0;
printf("请输入一个波兰表达式,数字之间,运算符之间以空格隔开,最后表达式以#号结束\n");
scanf("%c", &c);
while(c != '#')
{
while (isdigit(c) || c == '.') //判断字符是否为数字和小数点 ,对字符进行处理
{
//做一个缓冲区
str[t++] = c;
str[t] = '\0';
if (t >= 10)
{
printf("error:the single data is too larger to contain!");
return -1;
}
scanf("%c", &c);
if (c == ' ')
{
g = atof(str);//把char数组转化为double
Push(&s, g); //把转化成double类型的g入栈
t = 0; //t置零,用于下次缓冲
break;
}
}
switch (c) //对运算符进行分类计算
{
case '+'://如果是+,先将栈的两个数据pop出栈,将+计算后的结果push入栈
Pop(&s, &e);
Pop(&s, &f);
Push(&s, f + e);
break;
case '-':
Pop(&s, &e);
Pop(&s, &f);
Push(&s, f - e);
break;
case '*':
Pop(&s, &e);
Pop(&s, &f);
Push(&s, f * e);
break;
case '/':
Pop(&s, &e);
Pop(&s, &f);
if (e != 0)
{
Push(&s, f / e);
}
else {
printf("error: the number should not be a zero !");
return -1;
}
break;
}
scanf("%c", &c); //在循环中不断的输入字符
}
Pop(&s, &g);
printf("the final result is %f.\n", g);
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
输入后缀表达式 1 10 + 5 * 1 / #
输出结果: