表达式转换(C语言实现)

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

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

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

输入样例: 2+3*(7-4)+8/4 输出样例: 2 3 7 4 - * + 8 4 / +

本题的思路:
该题我觉得难就难在需要注意许多的测试点
1.存在小数
2.存在负数,且如果该负数没有出现在中缀表达式守,就会以(-?)的形式出现
3.同样存在带有正号的正数(有点奇怪…),以(+?)形式出现,但是输出到后缀表达式中不能带有正号
4.存在括号的嵌套

我的思路:
因为存在不止一位的数字,所以我选择将每个数字和符号之间间隔一个自己用来判断的字符(我用的是y)接下来就是大体的实现步骤,然后其余测试点的细节再在代码中添加
1.创建一个数组用来储存转换的结果,一个堆栈用来存储运算符
2.每当读到一个数字,就将该数字存入结果表达式
3.每当读到一个符号:
①如果此时的符号堆栈没有符号,就将该符号存入
②如果此时符号堆栈有符号,若优先级小于该符号,直接存入
③如果优先级大于该符号,弹出所有符号

#include<stdio.h>
#include<string.h>
int main()
{
	char result[100];//用于储存结果的数组 
	char symbol[100];//用于储存符号的堆栈
	int top = 0;//符号堆栈的栈顶指针
	int length;
	
	char s[100];//题目输入的中缀表达式
	scanf("%s",&s);
	length = strlen(s);
	
	int i,j,flag,k;
	for(j = 0;j < 100;j++)
		result[j] = 'y';
	for(j = 0,k = 0;j < length;j++){
		if(s[j] == '(' || s[j] == ')')
			k++;
	}
	i = j = flag = 0;
	while(s[i] != '\0'){//当中缀表达式未结束 
		if(s[i] >= '0' && s[i] <= '9'){//当输入的为数字时
			if((s[i+1] >= '0' && s[i+1] <= '9') || s[i+1] == '.'){//当不为个位数时
				result[j++] = s[i];
			}else{//当为个位数时 
				result[j] = s[i];
				j += 2;
			}
		}else{//当输入的为符号时 
			if(top == 0 && (s[i] != '.' && j != 0)){//当栈为空,符号直接入栈 
				symbol[top++] = s[i];
			}else if(s[i] == '*' || s[i] == '/'){//当符号为乘除时直接入栈 
				symbol[top++] = s[i];
			}else if(s[i] == '+' || s[i] == '-'){//当符号为加减时 
				if(symbol[top-1] != '*' && symbol[top-1] != '/'){//当符号的优先级等于加减时
					if(s[i] == '-' && s[i-1] == '('){//如果输入为(-?)时
						result[j++] = '-';//向结果表达式中存入负号
						flag = 1;//说明结果表达式中有负数存在
					}else if(s[i] == '+' && s[i-1] == '('){//如果输入为(+?)时
						flag = 2;
						k++;
					}else if(s[i] == '-' && j == 0){//第一个数为负数时
						result[j++] = '-';
					}else if(s[i] == '+' && j == 0){//第一个数为正数时
						k++;
					}else{//如果不是上述情况直接存入
						symbol[top++] = s[i];
					}
				}else{//当符号的优先级高于加减时
					while(top && symbol[top-1] != '('){
						result[j] = symbol[top-1];
						j += 2;top--;
					}
					symbol[top++] = s[i];
				}
			}else if(s[i] == '('){//当输入左括号时
				symbol[top++] = s[i];
			}else if(s[i] == ')'){//当输入右括号时
				while(symbol[top-1] != '('){//将符号堆栈中的非(符号压入结果表达式中 
					result[j] = symbol[top-1];
					j += 2;
					top--;			
				}
				top--;
			}else if(s[i] == '.'){
				result[j++] = s[i];
			}
		}
		i++;
	}
	while(top){//当符号栈不为空,将其中剩余的所有符号全部压入结果表达式
		result[j] = symbol[top-1];
		j += 2;top--;
	}
	for(j = 0,i = 1;i <= length - k;){//length是表达式的长度,k是表达式中')','(','+'(正数前的正号)的数量,当i等于length-k就代表已输出完成
		if(result[j] != 'y'){
			printf("%c",result[j++]);
			i++;
		}else{
			printf(" ");
			j++;
		}
	}
}

可以注意一下
-2*(+3)
1314+25.5*12
是比较易错的测试点

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值