算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+、-、*、\以及左右括号(),表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
代码一(PTA就是不过,说编译错误,我也很无奈)
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
using Status = int;
using Elemtype = char;
#define INITSIZE 30
#define INCREMENT 10
#define MAX 20
#define OVERFLOW -2
#define ERROR 0
#define OK 1
struct stack {
Elemtype *base;
Elemtype *top;
int stacksize;
};
Status InitStack(stack *s) {
s->base = (Elemtype *) malloc(INITSIZE * sizeof(Elemtype));
if (!s->base) {
printf("存储空间分配失败\n");
exit(OVERFLOW);
}
s->top = s->base;
s->stacksize = INITSIZE;
return OK;
}
Status Push(stack *s, Elemtype e) {
if (s->top - s->base >= s->stacksize) {
printf("栈已经满了,正在重新分配空间。\n");
s->base = (Elemtype *) realloc(s->base, (INITSIZE + INCREMENT) * sizeof(Elemtype));
if (!s->base) {
printf("重新分配空间。\n");
exit(OVERFLOW);
}
s->top = s->base + s->stacksize;
s->stacksize += INCREMENT;
}
*s->top++ = e;
return OK;
}
Status Pop(stack *s, Elemtype *e) {
if (s->top - s->base == 0) {
printf("栈空\n");
exit(OVERFLOW);
}
*e = *--s->top;
return OK;
}
Status Change(stack *s, Elemtype str[]) {
int i = 0;
Elemtype e;
InitStack(s);
//中最转化为后缀,从左向右扫描入栈,出栈后的结果逆序就是后缀表达式
while (str[i] != '\0') {
while (isdigit(str[i])) {//直接输出
printf("%c", str[i++]);
if (!isdigit(str[i])) {
printf(" ");
}
}
if (str[i] == '+' || str[i] == '-') {
if (s->top - s->base == 0) {
Push(s, str[i]);
} else {
do {
Pop(s, &e);
if (e == '(') {
Push(s, e);
} else {
printf("%c ", e);
}
} while (s->top - s->base > 0 && e != '(');
Push(s, str[i]);
}
} else if (str[i] == ')') {
Pop(s, &e);
while (e != '(') {
printf("%c ", e);
Pop(s, &e);
}
}
//刚开始测试1+((2+3)x4)-5一直不对,后来发现书写的符号和计算机的不一样,于是再多加了条件判断‘x’和‘X’
else if (str[i] == '*' || str[i] == '/' || str[i] == '(' || str[i] == 'x' || str[i] == 'X') {
Push(s, str[i]);
} else if (str[i] == '\0') {
break;
} else {
printf("\n输入格式错误!\n");
exit(OVERFLOW);
}
i++;
}
while (s->top - s->base) {
Pop(s, &e);
printf("%c ", e);
}
return OK;
}
int main() {
Elemtype str[MAX];
stack S;
scanf("%s", str);//直接读入一整行,读到回车结束读取,然后在末尾添加'\0'字符
Change(&S, str);
return 0;
}
成功代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int IsNum( char c);
int IsZhengfu( char c);
int Compare( char a, char b);
int main()
{
char str1[21];
char str2[21];
int len;
int flag =0; //表示str2是否为空
int i,j;
int space =0;
scanf("%s",str1);
len = strlen(str1);
for( i=0; i<len; i++)
{
if(IsNum(str1[i]))
{
//str1[i]是数字则输出
if( space )
{
printf(" ");
space = 0;
}
printf("%c",str1[i]);
}
else if( IsZhengfu(str1[i]) && (i? !IsNum(str1[i-1]) && str1[i-1]!=')':1))
{
//若第一个符号是负号或者出现连续两个符号
if( str1[i]=='-')
{
if(space)
{
printf(" ");
space = 0;
}
printf("%c",str1[i]);
}
}
else
{
//其他符号
if( flag)
{
if( str1[i]==')')
{
//str2出栈直至遇到(
while( flag--)
{
if(str2[flag]=='(') break;
printf(" %c",str2[flag]);
}
}
else
{
while( flag )
{
//str2内不为空,比较栈顶与str1[i]的优先级
if( Compare( str2[flag-1],str1[i]))
{
//若str1优先级低,出栈
printf(" %c",str2[--flag]);
}
else break;
}
str2[flag++] = str1[i];
}
}
else str2[flag++] = str1[i];
for ( j=0; j<flag; j++)
{
if( str2[j]!='(')
{
//遇见‘(’不输出空格
space = 1;
break;
}
}
}
}
while (flag)
{
printf(" %c",str2[--flag]);
}
return 0;
}
int IsNum( char c)
{
//c是数字,注意题目数据会有小数
return ( c >='0'&&c<='9')||c=='.';
}
int IsZhengfu( char c)
{
return c=='+' || c=='-';
}
int Compare( char a, char b)
{
//比较两个符号优先级
//连续的两个case语句表示这两个case是同一种情况
if( b==')') return 1;
if( b=='(' || a=='(') return 0;
switch(b)
{
case '+':
case '-':
return 1;
case '*':
case '/':
switch(a)
{
case '+':
case '-':
return 0;
case '*':
case '/':
return 1;
}
}
}