中缀表达式转化为后缀表达式
首先声明,这个代码不全是我写的,以至于个人认为一些函数比较反人类。。。不过不要在意这些细节啦。。。好了,敲黑板,讲重点了
首先是这道题的整体的思路
1.读取中缀表达式
2.对其进行遍历,一次读入一个字符,读到'\0',则停止读入。
3.对字符处理:
若是数字,直接输出
若是左括号,直接入栈
若是右括号,则符号栈一直弹出栈顶元素,直到弹出一个左括号
若是加减乘除运算符,则需要与符号栈栈顶元素比较优先级,
如果栈顶元素是左括号,则该运算符入栈
如果栈顶元素优先级>=当前运算符,则弹出栈顶元素,继续比较
如果栈顶元素优先级<=当前运算符,则该运算符入栈
下面是一些子函数和必要的子程序。
这里包括开辟一个用于存储加减乘除和括号等非数字的符号栈,而与之相配的就是出栈,入栈,取顶元素,而且为了确定符号栈是否为空需要开辟一个类似于flag的东西,这里是count,表示符号栈的里元素的数量。总之归纳为开栈,出入栈,取顶,栈内元素数量标记。记住:这些栈是用来储存非数字类符号的!!!,为啥要储存?因为当你扫描中缀表达式中的非数字类符号时,你需要对其进行入栈,但是这里又不是扫到一个就直接入栈,而需要比较判断优先级的,来决定何时入栈。这里就涉及到括号以及加减乘除的优先级的问题了这里的代码把所有字符包括数字也赋予了优先级,规则如下
1.字符串结束标志'\0'优先级为-1
2.数字为0
3.加减为1
4.乘除为2
5左括号为3
6.右括号为4
个人认为,这里优先级主要是应用于加减乘除运算符比较,其余的符号的优先级更多的是当做标签,用作判断用。
另外还有一个empty函数,用来判断符号栈是否为空。
好了,下面是一些问题
1.如何进行遍历?
这里用了while循环进行遍历,循环一次,读入一个字符,并计算该字符的优先级,从而判断该字符是数字,还是左右括号,或是加减乘除。
注意:!!!这里的while的括号中是1,可能有疑问,一直是1,不就一直读入,死循环了吗?但是下面有一个对END的if判断,如果遍历完了,也就是读到了‘\0',就会break;从而跳出while循环,而且在这之前,会把所有的‘\0'除去。
2.数字的读取问题?
这里用q指针指着这次第一个读到的数字字符开始,用一个for循环,q++,保证q指针在++的过程中所指元素全是数字或是小数点。然后利用一个while循环,p指针同时跟进并输出数字字符。
3.左右括号的处理?
左括号直接压栈,右括号符号栈一直弹出栈顶元素,直到弹出一个左括号。
4.加减乘除的处理?
如果优先级大于栈顶元素,或是栈顶元素为左括号,则直接入栈;
如果优先级小于或等于,且栈顶元素不为左右括号时则一直弹出栈顶元素,注意弹出时栈不为空!(这就是三个条件)
好了,下面是一些细节问题
注意:涉及到弹出元素时,一定要保证符号栈不为空!!!
注意:处理完一个字符是,p指针一定要++!!!
注意:第一个输出的一定是数字,于是用于保证第一个输出的字符前没有空格的flag标签放在了数字那里!!!
注意:每次输出,除了第一个字符之外,之前先打印空格!!!
#include <stdio.h>
//定义优先级
const int END = -1;
const int VALUE = 0;
const int PLUS_MINUS = 1;
const int MULTI_DIV = 2;
const int OPEN_PAREN = 3;
const int CLOSE_PAREN = 4;
//定义符号对象的优先级
int priority(const char c){
switch (c){
case '\0':return END;
case '+':return PLUS_MINUS;
case '-':return PLUS_MINUS;
case '*':return MULTI_DIV;
case '/':return MULTI_DIV;
case '(':return OPEN_PAREN;
case ')':return CLOSE_PAREN;
default: return VALUE;
}
}
//符号栈
char stack[30] = "\0";
int count = 0;
//栈函数
int empty(){
return !count;
}
const char top(){
return stack[count - 1];
}
//返回栈顶元素并将其弹出
char pop(){
return stack[--count];
}
//将元素压栈
void push(char c){
stack[count++] = c;
}
//中缀表达式
char midfix[30] = "\0";
int main(){
//首次输出的指示器,用于判断是否加空格
int flag = 0;
//将操作数与符号划分开来
char *p = NULL, *q = NULL;
int postIndex = 0;//没有用!!!
int curPriority;
scanf("%s", midfix);
p = q = midfix;
while (1){
curPriority = priority(*p);
//读取完毕
if (curPriority == END ){
while (!empty()){
putchar(' ');
putchar(pop());
}
break;
}
//当前读入数值,直接输出
if (curPriority == VALUE){
//使用指针q进行搜索,直到q指向下一个符号或字符串末尾为止
for (q = p;*q<='9'&&*q>='0'||*q=='.';q++);
if (flag++)
putchar(' ');
while (p != q)
putchar(*p++);
}//左括号,压栈
else if (curPriority == OPEN_PAREN){
push('(');
++p;
}//读入右括号,将符号栈内元素弹出,直到遇到左括号
else if (curPriority == CLOSE_PAREN){
char c = 0;
while (!empty()){
c = pop();
if (c == '(')
break;
putchar(' ');
putchar(c);
}
++p;
}//读入四则运算符
else{
while (curPriority <= priority(top())&&top()!='('&&!empty()){
putchar(' ');
putchar(pop());
}
push(*p++);
}
}
putchar('\n');
return 0;
}