题目:
表达式转换
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+
、-
、*
、\
以及左右括号()
,表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
注意事项:
一定要注意小数,多位数字,负数,空格的情况
测试用例为:
序号 | 输入 | 输出 | 说明 |
---|---|---|---|
0 | 2+3*(7-4)+8/4 | 2 3 7 4 - * + 8 4 / + | 正常测试6种运算符 |
1 | ((2+3)*4-(8+2))/5 | 2 3 + 4 * 8 2 + - 5 / | 嵌套括号 |
2 | 1314+25.5*12 | 1314 25.5 12 * + | 运算数超过1位整数且有非整数出现 |
3 | -2*(+3) | -2 3 * | 运算数前有正负号 |
4 | 123 | 123 | 只有一个数字 |
5 | 3 * ( 4 + 2 ) | 3 4 2 + * | 有空格 |
步骤:
1.初始化一个栈stc:用来存各种各样的符号;初始化一个字符数组str来存最后结果;
2.从左至右扫描中缀表达式;
3.提取对象函数gotop,用来提取这个对象来应对多位数字如:1233,和负数的情况具体函数看代码;
如果这个对象是个数就直接把他弄到数组里面,第一个肯定是数
4.遇到运算符时,比较其与stc栈顶运算符的优先级:
1.如果stc为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
2.否则,若优先级比栈顶运算符的高,也将运算符压入stc
3.否则,否则弹出栈中元素直到优先级比栈顶高或空栈为止;
5.遇到括号时:
1.如果是左括号“(”,则直接压入stc;
2.如果是右括号“)”,则依次弹出stc栈顶的运算符,并复制入str后面,直到遇到左括号为止,此时将这一对括号弹出;
6.如果遇到‘ ’,直接nexti++然后continue。
7.重复步骤2至5,直到表达式的最右边;
8.将stc中剩余的运算符依次弹出并复制入str;
9.即为中缀表达式对应的后缀表达式,输出数组即可
全注释代码:
#include <iostream>
#include <stack>
#include <string.h>
using namespace std;
///是否是数字
int IsNumber(char a)
{
return a >= '0' && a <= '9';
}
///从字符串start处开始提取操作数或操作符,并返回下一次提取的开端和提取的对象
int getop(char *src, int start, int &nextstart, char *token) //这里用nextstart和token都是可以直接操作的
{
int i, j;
if (IsNumber(src[start]))
{ ///是一个无符号数
for (i = 0; IsNumber(src[start + i]) || src[start + i] == '.'; i++) //如果这一位是'.''或者是数字'就是把小数和多位数字都包括了
{ ///复制给token
token[i] = src[start + i];
}
token[i] = 0;
nextstart = start + i; ///下一次提取的开端
return 1;
}
else if ((src[start] == '+' || src[start] == '-') && (start == 0 || src[start - 1] == '('))
{ ///传进来的这一位是符号的话并且是一个负号数的话start == 0 || src[start - 1] == '('是限制符号数的
if (src[start] == '-')
{
token[0] = src[start];
j = 1; //负号的话就把负号给token[0]然后j=1就是从第二位开始把负号输进去
}
else
{ ///去掉正号
j = 0; //也就是直接把数输进去
}
for (i = 1; IsNumber(src[start + i]) || src[start + i] == '.'; i++)
{ ///复制给token
token[j++] = src[start + i];
}
token[j] = 0;
nextstart = start + i; ///下一次提取的开端
return 1;
}
else
{ ///不是数
token[0] = src[start]; ///复制操作符
token[1] = 0; //标识结束
nextstart = start + 1; ///下一次提取的开端
}
return 0;
}
///定义优先级。括号最低
int Prior(char ch)
{
int pri = 0;
switch (ch)
{
case '(':
pri = 1;
break;
case '+':
case '-':
pri = 2;
break;
case '*':
case '/':
pri = 3;
break;
}
return pri;
}
///表达式转换
void Zhong2Hou(char *src, char *str) // str是装最后结果的数组
{
stack<char> stc;
int i, j, nexti;
char token[100];
for (i = 0, j = 0; src[i]; i = nexti)
{
if (src[i] == ' ')//如果为空格就不用管他
{
nexti++;
continue;
}
int isnumber = getop(src, i, nexti, token); ///提取这个对象,就是处理多位数字和字母如果是个数就返回1了;
if (isnumber)
{ ///是个数
int k = 0; ///复制到str后
for (k = 0; token[k]; k++)
{
str[j] = token[k];
j++;
}
str[j++] = ' '; ///用空格分隔,str就装数的对象了;
}
else if (src[i] == '(')
{ ///左括号直接入栈
stc.push(src[i]);
}
else if (src[i] == ')')
{ ///右括号则弹出栈中全部操作符并复制到str后,直到左括号为止
while (stc.top() != '(')
{
str[j++] = stc.top();
stc.pop();
str[j++] = ' '; ///用空格分隔
}
stc.pop(); ///弹出左括号
}
else
{ ///是个一般的四则运算符
if (stc.empty())
{ ///空栈直接入栈
stc.push(src[i]);
}
else if (Prior(src[i]) > Prior(stc.top()))
{ ///优先级高于栈顶则入栈
stc.push(src[i]);
}
else
{ ///否则弹出栈中元素直到优先级比栈顶高或空栈为止
while (!stc.empty() && Prior(src[i]) <= Prior(stc.top()))
{
str[j++] = stc.top();
stc.pop();
str[j++] = ' ';
}
stc.push(src[i]); ///将该操作符入栈
}
}
}
while (!stc.empty())
{ ///弹出栈中全部元素
str[j++] = stc.top();
stc.pop();
str[j++] = ' ';
}
str[j - 1] = 0; ///最后一个空格赋值为0就不打印最后的空格了
}
int main(void)
{
char src[100] = "", str[100] = "";
cin.getline(src, 100); ///输入
Zhong2Hou(src, str); ///转换
cout << str; ///打印
system("pause");
return 0;
}