这题几乎写了一天。。。。烦死我了。。。。不过总比写了一天还写不出的非递归汉诺塔强。。。。。那个明天再不搞定,我就。。。。。。。。也不能怎样。
习题3.11 表达式转换(25 分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+
、-
、*
、\
以及左右括号()
,表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ERROR -1
#define MAXLENTH 100
typedef char ElementType;
typedef struct snode* PtrToSnode;
struct snode
{
ElementType data;
PtrToSnode next;
};
typedef PtrToSnode mystack;
/**< 这些都是堆栈的基本操作,不解释 */
bool isEmpty(mystack ms);
mystack create();
bool pushdata(mystack ms, ElementType x);
ElementType popdata(mystack ms);
/**< 将操作符转换成数字,可用于比较优先级,很简单,也不解释 */
int OprToDig(char ch);
int OprToDig(char ch)
{
int val;
switch (ch)
{
case '+':
val = 1;
break;
case '-':
val = 1;
break;
case '*':
val = 2;
break;
case '/':
val = 2;
break;
case '(':
val = 0;
break;
case ')':
val = 0;
break;
default:
printf("%c is invalid Char\n", ch);
break;
}
return val;
}
mystack create()
{
mystack ms = (mystack)malloc(sizeof(struct snode));
ms->next = NULL;
return ms;
}
bool isEmpty(mystack ms)
{
return (ms->next == NULL);
}
bool pushdata(mystack ms, ElementType x)
{
bool rlt = false;
PtrToSnode tmpcell = (PtrToSnode)malloc(sizeof(struct snode));
tmpcell->data = x;
tmpcell->next = ms->next;
ms->next = tmpcell;
rlt = true;
return rlt;
}
ElementType popdata(mystack ms)
{
if(isEmpty(ms))
{
printf("empty stack.\n");
return ERROR;
}
else
{
ElementType rlt = ms->next->data;
PtrToSnode tmpcell;
tmpcell = ms->next;
ms->next = tmpcell->next;
free(tmpcell);
return rlt;
}
}
int main()
{
bool flag = false; /**< 是不是操作符之后,是就打印空格 */
bool isFirst = true; /**< 是不是第一个数字 */
mystack stk = create();
char exrn[MAXLENTH];
gets(exrn);
int i = 0;
while(exrn[i]!='\0')
{
/**< line107到line125都是用来处理数字的 */
/** (i==0) && (exrn[i]=='-'||exrn[i]=='+') 表示第一个数字带有正负号的
* ((exrn[i]>='0' && exrn[i]<='9')||exrn[i]=='.') 常规数字,和小数点
* ((exrn[i]=='-'||exrn[i]=='+')&&exrn[i-1]=='(') 括弧后面紧跟一个+或者-号,证明这个符合是用来表示正负号的
*/
if(((i==0) && (exrn[i]=='-'||exrn[i]=='+')) || ((exrn[i]>='0' && exrn[i]<='9')||exrn[i]=='.') || ((exrn[i]=='-'||exrn[i]=='+')&&exrn[i-1]=='('))
{
if(flag && !isFirst) /**< 之前出现过操作符,并且不是第一个数字,所以就打印空格 */
{
printf(" ");
flag = false;
}
isFirst = false;
if(exrn[i]=='+') /**< 如果这时exrn[i]是一个+,证明它是正负号,所以直接忽略跳过 */
i++;
printf("%c", exrn[i]);
i++;
while((exrn[i]>='0' && exrn[i]<='9')||exrn[i]=='.')
{
printf("%c", exrn[i++]);
}
continue;
}
else
{
flag = true;
if(exrn[i]=='(') /**<遇到(,直接将(压入栈 */
{
pushdata(stk, exrn[i]);
}
else if(exrn[i]==')') /**< 遇到)后,将栈内元素直接输出,直至遇到( */
{
ElementType ch ;
while((ch = popdata(stk))!='(')
{
printf(" %c", ch);
}
}
else
{
if(isEmpty(stk)) /**< 这里处理一个特殊状况,当栈空时候,无论遇到什么操作符,都是入栈处理 */
{
pushdata(stk, exrn[i]);
}
else
{
if( OprToDig(exrn[i]) > OprToDig(stk->next->data) ) /**< 如果待处理操作符优先级比栈顶操作符高,则把待处理操作符入栈 */
{
pushdata(stk, exrn[i]);
}
/**< 如果待处理操作符优先级比栈顶操作符低,则把栈内元素一个个推出,直到待处理操作符优先级比栈顶操作符高,然后把待处理操作符入栈*/
else if( OprToDig(exrn[i]) <= OprToDig(stk->next->data) )
{
do
{
//printf("exrn %c:%d stk %c:%d\n",exrn[i], OprToDig(exrn[i]), stk->next->data, OprToDig(stk->next->data));
printf(" %c", popdata(stk));
//printf("exrn %c:%d stk %c:%d\n",exrn[i], OprToDig(exrn[i]), stk->next->data, OprToDig(stk->next->data));
}while( (stk->next!=NULL)&&(OprToDig(exrn[i]) <= OprToDig(stk->next->data)) ); /**< 注意考虑栈空情况 */
pushdata(stk, exrn[i]);
}
}
}
}
i++;
}
while(!isEmpty(stk))
{
printf(" %c", popdata(stk));
}
system("pause");
}