后缀表达式计算方式
规则:从左至右遍历表达式的每一个数字和符号,遇到数字就进栈,遇到符号,就将栈顶俩个数字出栈并进行运算,运算结果进栈,直到获得结果。
举例:后缀表达式 9 3 1 - 3 * + 10 2 / +
1.初始化一个空栈,这个栈用来对要运算的数字进出使用
2.后缀表达式中前三个都是数字,所以9,3,1进栈。
3.接下来是“ -”,所以栈中的1作为减数,3出栈作为被减数,并运算得到二,然后将二进栈。
4.接着是数字3进栈
5.后面是"*",也就意味着将3和2出栈进行运算,得到的结果6进栈
6.接下来是"+",将6和9出栈相加得到的结果15进栈
7.10和2进栈
8.后面是"/",将10和2出栈进行运算得到的结果5进栈
9.后面的是"+",将15和5出栈相加得到最终结果20
10.将最后结果出栈,栈为空。
既然用了后缀表达式后计算器显得没有这么难,但我们还得学会怎么将一行中缀表达式转换为后缀表达式,否则等于没有学
将中缀表达式转换为后缀表达式
规则:
从左边到右边遍历中缀表达式的每一个数字和符号,若是数字就输出,即成为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是又括号或优先级不高于栈顶符号,则栈顶元素依次出栈并输出,并将当前符号进栈,直到最终输出后缀表达式为止
举例:9+(3-1)3+10/2
1.初始化一空栈,用来对符号进出栈使用
2.第一个数字是9,输出9,后面是 +号,进栈,
3.第三个是(,依然是符号,因为是左括号,还未配对,所以进栈
4.第四个字符是数字3,输出,总表达式为9 3,接着是 -,进栈
5.接下来是数字1,输出,总表达式为9 3 1,后面是符号),此时,我们需要匹配此前的 (,所以栈顶依次出栈,并输出,直到遇到 (,出栈结束,此时左括号上方只有 -,因此输出 -,总的表达式为9 3 1 -
6.紧接着是符号 * ,因为此时栈顶符号为 +,优先级低于,因此不输出,*进栈,
接着是数字3,输出,表达式为9 3 1 - 3
7.之后的符号是 +,此时当前栈顶元素 *比这个+优先级更高,因此栈中元素出栈并输出(因为没有比+更低的优先级,所以全部出栈)总表达式为9 3 1 - 3 * +,
8.紧接着是数字10,输出,后面是符号 /,所以进栈
9.最后一个数字2,输出
10.因为到了最后,所以将栈中符号全部输出,得到后缀表达式
掌握这俩个后,简单的计算器就没有这么难了
#include<dtdio.h>
#include<stdlib.h>
#include<>memory.h>
#define MAXSIZE 100
typedef struct MStack
{
char data[MAXSIZE];
int top;
};
MStack *InitStack()
{
MStack *ms;
ms = (MStack*)malloc(sizeof(MStack));
memset(ms->data, 0, MAXSIZE);
ms->top = -1;
return ms;
}
void PushStack(MStack *ms, char e)
{
if (ms->top == MAXSIZE - 1)
{
printf("栈满溢出");
return;
}
ms->data[++ms->top] = e;
}
void PopStack(MStack *ms, char *e)
{
if (ms->top == -1)
{
printf("栈空!");
return;
}
*e = ms->data[ms->top--];
}
int PriCal(char c)
{
if (c == '-' || c == '+')return 1;
if (c == '*' || c == '/')return 2;
if (c == '(' || c == ')')return 3;
return false;
}
int main()
{
MStack *ms;
MStack *msn;
msn = InitStack();
ms = InitStack();
char above = 9;//保存上一次的输入值,检测输入算式是否合法
char c;
char num;
int e;
c = getchar();
//以下是将普通中缀表达式改为后缀表达式
while (1)
{
e = 0;
if (c <= '9' && c >= '0')
{
if (ms->top != -1)
{
if (above != '+' && above != '-' && above != '*' && above != '/' && above != '(')
{
printf("输入算式有错,请检查后重新运行此程序!");
return -1;
}
}
while (c <= '9' && c >= '0')
{
e = e * 10 + c - '0';
above = c;
c = getchar();
}
PushStack(msn, (char)(e + '0'));
}
if (c == '+' || c == '-' || c == '*' || c == '/')
{
if (!(above != ')' || (above <= '9' && above >= '0')))
{
printf("输入算式有错,请检查后重新运行此程序!");
return -1;
}
if (ms->top == -1)
PushStack(ms, c);
else if (PriCal(ms->data[ms->top]) >= PriCal(c))
{
while (PriCal(ms->data[ms->top]) >= PriCal(c))
{
if (ms->data[ms->top] == '(')break;
num = c;
PopStack(ms, &num);
PushStack(msn, num);
}
PushStack(ms, c);
}
else PushStack(ms, c);
}
if (c == '(' || c == ')')
{
if (c == '(')
{
if (above != '+' &&above != '-' &&above != '*' &&above != '/'&&ms->top != -1)
{
printf("输入算式有错,请检查后重新运行此程序!");
return -1;
}
PushStack(ms, c);
}
if (c == ')')
{
if (above < '0' || above > '9')
{
printf("输入算式有错,请检查后重新运行此程序!");
return -1;
}
while (c != '(')
{
PopStack(ms, &c);
if (c != '(')
PushStack(msn, c);
}
}
}
above = c;
if (c == '\n')break;
else c = getchar();
}
while (msn->top != -1)
{
PopStack(msn, &c);
PushStack(ms, c);
}
while (ms->top != -1)
{
if (ms->data[ms->top] <= '0' + 255 && ms->data[ms->top] >= '0')//原本数据范围是'0'-'9',如果要计算10以外则需要加大为'0'-'0'+255
{
PopStack(ms, &c);
PushStack(msn, c);
}
if (ms->data[ms->top] == '+')
{
PopStack(ms, &c);
PopStack(msn, &c);
PopStack(msn, &num);
num = (int)(num - '0') + (int)(c - '0') + '0';
PushStack(msn, num);
}
if (ms->data[ms->top] == '-')
{
PopStack(ms, &c);
PopStack(msn, &c);
PopStack(msn, &num);
num = (int)(num - '0') - (int)(c - '0') + '0';
PushStack(msn, num);
}
if (ms->data[ms->top] == '/')
{
PopStack(ms, &c);
PopStack(msn, &c);
PopStack(msn, &num);
num = (char)(int)(num - '0') / (int)(c - '0') + '0';
PushStack(msn, num);
}
if (ms->data[ms->top] == '*')
{
PopStack(ms, &c);
PopStack(msn, &c);
PopStack(msn, &num);
num = (int)(c - '0')*(int)(num - '0') + '0';
PushStack(msn, num);
}
}
printf("%d", msn->data[msn->top] - '0');
return 0;
}