1-3 表达式转换 (25分) HBU-DS 实验
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+
、-
、*
、\
以及左右括号()
,表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
~
依旧是比较坎坷的一道题。
思路
先不考虑细节,首先,大致思路是:如果遇到数字就直接输出,如果遇到符号,判断他是不是比现在栈顶的符号优先级高,如果高的话就入栈,低的话(栈里的元素优先级高),就把栈里所有比他高的符号都出栈(如果优先级相同也出栈,因为相同优先级从左至右运算)。所有应该出栈的元素出栈之后,就把当前元素入栈。
注意,‘(’ 这个优先级在栈里是最低的,而在栈外最高。
好的,现在来说细节。我遇到的问题有三个:格式,小数+非单位数(我刚开始按照整数写的,一个都过去),数字带着+ - 号。
格式:就设置一个cnt,如果第一次输出数字就直接数字,否则就空格+数字。
小数+非单位数:判断下一个是不是小数点或者数字,如果是就输出,再判断
正负号:出现正负号的地方,无非两个:这个字符串的第一个位置,以及左括号之后。设置一个last(char),存上上一个字符,每次循环先判断last是不是左括号,如果是就:如果是负号就输出符号然后continue,正号直接continue;
为了统一操作,将last的初始值设置为了左括号,以此作为开头是+ -号的补充。
代码
#include <iostream>
#include <string>
using namespace std;
int main()
{
char S[25];
int top = -1;
string str;
cin >> str;
S[++top] = '(';
char last = '(';
int cnt = -1;
for (auto it = str.begin(); it != str.end(); it++)
{
if (last == '(')
{
last = *it;
if (*it == '+')
continue;
if (*it == '-')
{
cout << "-";
continue;
}
}
last = *it;
if (*it <= '9' && *it >= '0')
{
if (++cnt == 0)
cout << *it;
else
cout << " " << *it;
while ((it + 1) != str.end() && (*(it + 1) <= '9' && *(it + 1) >= '0' || *(it + 1) == '.'))
{
it++;
cout << *it;
}
}
else if (*it == '+' || *it == '-')
{
if (S[top] == '(')
S[++top] = *it;
else
{
while (S[top] == '+' || S[top] == '-' || S[top] == '*' || S[top] == '/')
cout << " " << S[top--];
S[++top] = *it;
}
}
else if (*it == '*' || *it == '/')
{
if (S[top] == '(' || S[top] == '+' || S[top] == '-')
S[++top] = *it;
else
{
while (S[top] == '*' || S[top] == '/')
cout << " " << S[top--];
S[++top] = *it;
}
}
else if (*it == '(')
S[++top] = *it;
else if (*it == ')')
{
while (S[top] != '(')
{
cout << " " << S[top--];
}
top--;
}
}
while (S[top] != '(')
{
cout << " " << S[top--];
}
}