7-20 表达式转换 (25分)

题目链接:https://pintia.cn/problem-sets/15/problems/827

参考:https://blog.csdn.net/SiKongPop/article/details/77972879#comments(内附数个测试样例)

题意:

将输入中缀表达式转换为后缀表达式,输入字符包含'+' '-' '*' '/' '(' ')'。输出的每个操作数或操作符用空格间隔开,并且末尾不能输出多余空格

特别注意:操作数是可以有多位的,并且可以是小数,也就是说会包含有小数点,同时有的操作数是带符号的,带+号的不用输出+号,但是带-号的需要输出-号。

如果不把这些考虑进去注意,会有格式错误。

中缀到后缀的代码逻辑:

先准备一个栈S用来存储操作符,然后对输入的表达式的每个字符逐个处理。

对于输入的字符进行如下判断:

1)如果是'('直接压入栈S。

2)如果是'*' '/' '+' '-',将S的栈顶出栈输入的字符进行对比,如果输入操作符优先级小于等于栈顶操作符,则先输出栈顶操作符,再将输入的操作符压入栈S。

3)如果是')',S出栈,判断出栈的字符是不是'(',如果不是,则输出,否则,直接退出判断

处理多位数,小数以及带符号数的方法:

1)首先要清楚什么地方会出现带符号的数,第一种情况是在输出结果的开头,比如“-2+1”第二种情况是在括号里面,即紧接着'(',例如“(-2+1)”或者“(-2)+1”

2)如果(1)的条件满足,则顺着下去判断,逐个判断接下来输入的字符,如果仍然是数字或者小数点,就接着输出,如果遇到了非数字和非小数点的字符,就结束输出(此时一个操作数的输出已经完成,可以进行下一个输入的操作符的判断。)

3)如果只是不带符号的数,那么也跟(2)一样,从第一个数字开始逐个判断下一个数,与(2)同理

结果是如何输出的:

1)对于操作数,读入之后按要求处理后直接输出即可。

2)对于操作符一部分是在操作符入栈时优先级比栈顶操作符低级(或与栈顶操作符平级)的时候将栈顶操作符输出,剩下一部分在程序最后面,将剩下未出栈的操作符逐个出栈输出。

AC代码:

  1 #include <iostream>
  2 #include <string>
  3 #include <cstring>
  4 using namespace std;
  5 
  6 class stack_//定义栈
  7 {
  8 public:
  9     stack_() :r(-1) {}
 10     ~stack_() {}
 11     void push(char k)
 12     {
 13         s[++r] = k;
 14     }
 15     char pop()
 16     {
 17         if (r != -1)
 18             return s[r--];
 19         else
 20             return '';//如果栈为空,就返回''
 21     }
 22 public:
 23     char s[1000];
 24     int r;
 25 };
 26 
 27 int main()
 28 {
 29     stack_ operate_;//用来存放操作符
 30        char exp_[1000];//用来接收输入的表达式
 31     int cnt = 0;//计数,若为0说明是所输出结果的第一个字符,每次输出之后自增
 32 
 33     cin.getline(exp_, 1000);//输入表达式
 34     for (int i = 0; i < 1000; i++)//遍历所输入表达式的每一个字符
 35     {
 36         if ('' == exp_[i])break;//遍历完成,退出循环
 37         //判断:+-号是不是在'('后一个,或者在开头。这是出现带符号数字的惟二条件:
 38         //即出现在开头或以类似(-2+3)的形式出现,这里对是不是符合两个条件进行判断
 39         if (
 40             (i == 0 && (exp_[i] == '-' || exp_[i] == '+')) ||
 41             (i >= 1 && ((exp_[i] == '-' || exp_[i] == '+') && exp_[i - 1] == '('))
 42             )//判断条件是否满足
 43         {
 44             if (exp_[i] == '-')//如果是符号是'-'
 45             {
 46                 if (cnt == 0)
 47                 {
 48                     cout << '-'; cnt++;//为输出的第一个字符,不需要输出空格,直接输出'-',cnt自增
 49                 }
 50                 else
 51                 {
 52                     cout << ' ' << '-'; //若非第一个字符,则在前面先输出一个空格,因为cnt已不为0,不自增也可以
 53                 }
 54             }
 55             else if (exp_[i] == '+')//类似上面
 56             {
 57                 if (cnt == 0)cnt++;//注意此处,虽然并没有输出,但也要自加,否则输出完下面数字后的再下一次输出,会被误认为是第一次输出   
 58                 else
 59                 {
 60                     cout << ' '; //如果不是第一个,就只输出空格,因为+号是不用输出的
 61                 }
 62             }
 63 
 64             int j;
 65             for (j = i + 1;; j++)
 66             {
 67                 if ((exp_[j] >= '0' && exp_[j] <= '9') || exp_[j] == '.')
 68                 {
 69                     cout << exp_[j];//cnt不用自增,因为上面输出符号的时候已经处理过cnt了,
 70                     //此处输出数字的时候可以不考虑是第一次输出的情况
 71                 }
 72                 else break;//如果遇到的字符不是数字或者小数点,就可以结束此次输出
 73             }
 74             j--;//此时数组j下标放的是继上一次输出数字后的第一个非数字或小数点字符
 75             //下次循环理应从这里开始判断,但是因为进入下一次循环i要++,所以这里先--一次
 76             //抵消掉一次++,再赋给i
 77             i = j;
 78             continue;//下一次循环,开始下一个字符的判断
 79         }
 80         //判断输入字符是不是数字,此处
 81         else if (exp_[i] >= '0' && exp_[i] <= '9')
 82         {//逻辑与上面一个if类似
 83             if (cnt == 0)
 84             {
 85                 cout << exp_[i]; cnt++;
 86             }
 87             else
 88             {
 89                 cout << ' ' << exp_[i];
 90             }
 91             int j;
 92             for (j = i + 1;; j++)
 93             {
 94                 if ((exp_[j] >= '0' && exp_[j] <= '9') || exp_[j] == '.')
 95                 {
 96                     cout << exp_[j];
 97                 }
 98                 else break;
 99             }
100             j--;
101             i = j;
102             continue;
103         }
104         //判断输入字符是不是'('
105         else if (exp_[i] == '(')
106         {
107             operate_.push(exp_[i]);//如果是,可以直接压入栈
108             continue;//下一次循环,继续判断下一个输入的字符
109         }
110         //判断是不是输入'*'或'/',注意''里面只能含有操作符,
111         //不能带空格,否则判断的时候会出现错误
112         else if (exp_[i] == '*' || exp_[i] == '/')
113         {
114             while (1)
115             {
116                 char ch = operate_.pop();
117                 if (ch != '')//如果不是空栈
118                 {
119                     if (ch != '/' && ch != '*')//如果不是'/'或'*',说明栈顶操作符是优先级更低的,直接压入栈即可
120                     {
121                         operate_.push(ch);//先将刚刚出栈的栈顶元素重新压回栈
122                         operate_.push(exp_[i]);//再将操作符'*'或'/'压入
123                         break;
124                     }
125                     else//若遇到优先级相同的,先输出旧的,再压入新的
126                     {
127                         if (cnt == 0)
128                         {
129                             cout << ch; cnt++;
130                         }
131                         else
132                             cout << ' ' << ch;
133                         continue;
134                     }
135                 }
136                 else//空栈
137                 {
138                     operate_.push(exp_[i]);
139                     break;
140                 }
141             }
142         }
143         //判断'+'或'-'
144         else if (exp_[i] == '+' || exp_[i] == '-')//逻辑同上
145         {
146             while (1)
147             {
148                 char ch = operate_.pop();
149                 if (ch != '')
150                 {
151                     if (ch != '/' && ch != '*' && ch != '+' && ch != '-')
152                     {
153                         operate_.push(ch);
154                         operate_.push(exp_[i]);
155                         break;
156                     }
157                     else
158                     {
159                         if (cnt == 0)
160                         {
161                             cout << ch; cnt++;
162                         }
163                         else
164                             cout << ' ' << ch;
165                         continue;
166                     }
167                 }
168                 else
169                 {
170                     operate_.push(exp_[i]);
171                     break;
172                 }
173             }
174         }
175         //判断')'
176         else if (exp_[i] == ')')
177         {
178             char ch;
179             while (1)
180             {
181                 ch = operate_.pop();
182                 if (ch != '')//如果不为空栈
183                 {
184                     if (ch != '(')//若没有遇到'(',直接输出出栈的元素
185                     {
186                         if (cnt == 0)
187                         {
188                             cout << ch; cnt++;
189                         }
190                         else
191                             cout << ' ' << ch;
192                         continue;
193                     }
194                     else
195                     {
196                         break;//如果所出栈的字符是'(',则停止出栈
197                     }
198                 }
199                 else//如果是空栈,直接退出
200                 {
201                     break;
202                 }
203             }
204         }
205     }//big for      
206     //此处将没有出栈的操作符全部出栈
207     while (operate_.r != -1)
208     {
209         char ch = operate_.pop();
210         if (cnt == 0)
211         {
212             cout << ch; cnt++;
213         }
214         else
215             cout << ' ' << ch;
216     }
217     return 0;
218 }
AC代码:

 

原文地址:https://www.cnblogs.com/2020R/p/12398422.html