PAT表达式转换

表达式转换(25 分)

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。

输入格式:

输入在一行中给出不含空格的中缀表达式,可包含+-*\以及左右括号(),表达式不超过20个字符。

输出格式:

在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。

输入样例:

2+3*(7-4)+8/4

输出样例:

2 3 7 4 - * + 8 4 / +

一道非常恶心的题,从中缀表达式转为后缀表达式,大体思路到不难,用到了一个单调栈,遇到数值就输出,遇到操作符进栈,维护一个操作符优先级单调递增栈,注意括号的处理,但麻烦的是因为有小数点和正负数,如何把数值和运算符从字符串里提取出来。第一次写的时候没有注意这一点,以为数值都是一位数的,结果3个格式错误,2个答案错误,格式错误是因为把本来之间没有空格的多位数中间加了空格,答案错误是因为没有注意小数点。写这个题还是挺考验代码实现能力的。

#include<stdio.h>
#include<string.h>
int isNumber(char a){
	return a>='0' && a<='9';
}
//得到一个操作对象,记录在token里 
int get(char* str,int start,int *nextstart,char* token){
	int i,j;
	if(isNumber(str[start])){  //说明是一个无符号的数 
	    //把无符号数记录下来,注意小数点 
		for(i=0;isNumber(str[start+i])||str[start+i]=='.';i++){
			token[i]=str[start+i];
		}
		token[i]=0;
		*nextstart=start+i;// 下一次进行访问的位置 
		return 1;
	//有符号数,一种情况是第一位是正负号,另一种情况是上一位为括号	
	}else if((str[start]=='+'||str[start]=='-') && (start==0||str[start-1]=='(')){
		if(str[start]=='-'){ //输出负号 
			token[0]='-';
			j=1;
		}else{ //不输出正号 
			j=0;
		}
		//把有符号数记录下来,注意小数点 
		for(i=1;isNumber(str[start+i])||str[start+i]=='.';i++){
			token[j++]=str[start+i];
		}
		token[j]=0;
		*nextstart=start+i;//下一次访问的位置 
		return 1;
	}else{
		//为运算符 
		token[0]=str[start];
		token[1]=0;
		*nextstart=start+1;
	}
	return 0;
}
//定义优先级函数 
int ope(char a){
	if(a=='('){
		return 1;
	}else if(a=='*'||a=='/'){
		return 3;
	}else if(a=='+'||a=='-'){
		return 2;
	}
}
int main(void){
	char str[100],stack[100],token[100],ans[100];
	scanf("%s",&str);
	int top=-1;
	int next;
	int i,j;
	for(i=0,j=0;str[i];i=next){
		int isnumber=get(str,i,&next,token);
		//是数字的话直接存入数组里 
		if(isnumber){
			for(int k=0;token[k];k++){
				ans[j++]=token[k];
			}
			ans[j++]=' ';//用空格隔开 
	    }else if(str[i]=='('){ //遇到'('直接压入栈中 
		    stack[++top]='(';
	    }else if(str[i]==')'){ //遇到')'把括号里的所有运算符都弹出 
		    while(stack[top]!='('){
			    ans[j++]=stack[top--];
			    ans[j++]=' ';
		    }
		    top--;//把'(' 也弹出 
	    }else{//为普通运算符的情况 
		    if(top==-1){//空栈直接进栈 
			   stack[++top]=str[i]; 
		    }else if(ope(str[i])>ope(stack[top])){//把优先级比栈顶高的元素弹进栈里 
			   stack[++top]=str[i];
		    }else{
			    while(top!=-1 && ope(str[i])<=ope(stack[top])){//如果不比栈顶运算符优先级高,弹出,直到比栈顶操作符优先级高
				//或栈为空 
				    ans[j++]=stack[top--];
				    ans[j++]=' ';
			    }
			    stack[++top]=str[i];//把该运算符进栈 
		    }
	    }
	}
	//把栈中所有运算符都弹出 
	while(top!=-1){
		ans[j++]=stack[top--];
		ans[j++]=' ';
    }   
    ans[j-1]='\0';//最后一个空格去掉 
    printf(ans);//输出 
    return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值