我正在尝试将中缀转换为后缀。例如: "20 + 2 * 3 + (2*8 + 5(* 4" ->20 2 3 * + 2 8 * 5 + 4 * +这是我的代码:
Stack<Character> s = new Stack<Character>();
String postfix = "";
boolean enter = true;
String infixExpr = "20 + 2 * 3 + (2*8 + 5)* 4";
for(int i = 0;i<infixExpr.length();i++){
if(Character.isDigit(infixExpr.charAt(i)) == true){
postfix = postfix + infixExpr.charAt(i);
}
if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
if(s.isEmpty() == true){
s.push(infixExpr.charAt(i));
}
else{
if(s.peek() == '*' || s.peek() == '/' || s.peek() == '+' || s.peek() == '-'){
while(s.isEmpty()== false){
postfix = postfix + s.pop();
}
s.push(infixExpr.charAt(i));
}
else{
s.push(infixExpr.charAt(i));
}
}
}
if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
if(s.isEmpty() == true){
s.push(infixExpr.charAt(i));
}
else{
if(s.peek()== '+' || s.peek() == '-' || s.peek() == '('){
s.push(infixExpr.charAt(i));
}
else if(s.peek() == '*' || s.peek() == '/'){
while(s.isEmpty()== false){
postfix = postfix + s.pop();
}
s.push(infixExpr.charAt(i));
}
}
if(infixExpr.charAt(i) == '('){
s.push(infixExpr.charAt(i));
}
if(infixExpr.charAt(i) == ')'){
while(enter){
if(s.peek() == '('){
enter = false;
}
else{
postfix = postfix + s.pop();
}
}
}
}
}
正如写在顶部的那样,我想得到"20 2 3 * + 2 8 * 5 + 4 * +",但我得到"2023*+28*+54"这是错误的,我多次修改代码,但仍然看不到问题。如果有人能帮忙,那就太好了。
您没有在后缀变量上放置任何空格。您只检查当前字符是否是"有趣"字符之一(数字、运算符(,而不是检查它是否是空格。因此,如果当前字符是一个空格,则只需跳过它,并且不会将其复制到后缀中。
由于您在后缀中放置的唯一内容是您检查过的字符,因此您最终根本没有空格。
你可以这样解决它:
- 添加一个名为
inNumber
的布尔值,首先将其设置为 true。 - 每当您处理数字时,在将其添加到
postfix
之前,请检查inNumber
是否为真。如果是这样,请先添加一个空格。 - 如果刚刚处理了一个数字,请将
inNumber
设置为 true。 - 如果要处理运算符,请将
inNumber
设置为 false。 - 每当向堆栈添加任何运算符时,请先添加一个空格。
关于此inNumber
的想法是,所有属于同一数字的数字之间不应有空格。但是,如果在上一轮处理了运算符后将数字添加到postfix
,那么它属于一个新数字,因此那里应该有一个空格。
所以基本上,你的数字处理代码应该看起来像:
if(Character.isDigit(infixExpr.charAt(i)) == true){
if ( ! inNumber ) {
postfix += " ";
}
postfix = postfix + infixExpr.charAt(i);
inNumber = true;
}
在指示运算符的每个if
中,您应该inNumber = false
.
将运算符添加到后缀的每个位置都应如下所示:
postfix = postfix + " " + s.pop();
处理括号
您的另一个问题是()
的处理。
首先,您将检查(
和)
的代码放入if
中,以便*
和/
。当然,如果i
位置的字符是 *
或 /
,它不是(
或)
因此永远不会调用此代码。
因此,您应该将括号的if
移到与数字和运算符if
相同的级别。
此外,您对enter
的使用是错误的。如果你在括号内有括号,比如( 3 + ( 5 + 7 ) )
,那么在第一个)
,你会一直回到5
后面的括号,这没关系。但是enter
会变成假的,您将无法正确处理外部对。对于(3 + 5 ) * ( 7 + 2 )
也是如此,因为您不会在程序开始后将enter
设置为再次true
。
与其使用 enter
,不如弹出堆栈上的内容并检查它是否是(
:
if(infixExpr.charAt(i) == '('){
inNumber = false;
s.push(infixExpr.charAt(i));
}
if(infixExpr.charAt(i) == ')'){
inNumber = false;
char popped;
while ( ( popped = s.pop() ) != '(' ) {
postfix = postfix + " " + popped;
}
}
未弹出的运算符
最后,完成扫描输入后完成。但此时您仍然会有操作员在堆栈上等待!您必须将它们全部弹出并添加到postfix
.所以在循环之后,你应该有:
while ( ! s.isEmpty()) {
postfix += " " + s.pop();
}
补充说明:
- 如果您不使用所有这些
if
语句,而是使用switch
语句,那会更好、更清楚。 - 将布尔表达式与
true
进行比较是没有意义的。写if (s.isEmpty() == true)
的正确方法是if (s.isEmpty())
,而不是s.isEmpty() != true
使用! s.isEmpty()
。 - 您没有进行任何语法检查。我不确定这是否是因为这是家庭作业,但在现实生活中你应该检查每个
(
是否都匹配一个)
,每个运算符都有两个操作数,并且还要处理一开始可能有-
的负数。
问题是您没有添加空格。但是,您不能简单地在每个数字之间添加一个空格。您必须确保在整数的数字之间不会添加空格。为了解决这个问题,我只是在if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-')
后添加一个postfix += " ";
,然后在if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' )
之后再次添加。这背后的逻辑是,一旦你遇到一个运算符,你就知道操作员之前的一切都是数字。现在,当我运行程序时,输出是20 2 3 *+2 8 *+5 4
。运算符之间仍然需要添加一些空格,但我会让您处理。
修改后的代码:
if(infixExpr.charAt(i) == '+' || infixExpr.charAt(i) == '-'){
postfix += " ";
。
if(infixExpr.charAt(i) == '*' || infixExpr.charAt(i) == '/' ){
postfix += " ";
这是我为你回答的代码
#include<stack>
#include<iostream>
using namespace std;
bool high(char a,char b)
{
if(b==' ')
return true;
else if(a==b)
return false;
else if(a=='/')
return true;
else if(a=='*'&&b!='/')
return true;
else if(b=='/')
return false;
else if(a!='/'&&b=='*')
return false;
else if(b=='-')
return true;
else if(a=='-'&&b!='(')
return false;
else if(b=='(')
return true;
else if(a=='(')
return true;
else if(a==')')
return false;
}
main()
{
int k=0;
string s;
stack<char>s1;
s1.push(' ');
char ch;
while(cin>>ch)
{
if(ch=='(')
{
k=1;
s1.push(ch);}
else if(ch>47&&ch<58)
s.push_back(ch);
else if(high(ch,s1.top()))
s1.push(ch);
else if(!high(ch,s1.top())&&ch!=')')
{
while(!s1.empty()&&!high(ch,s1.top()))
{
s.push_back(s1.top());
s1.pop();
}
s1.push(ch);}
else if(ch==')')
{
while(!s1.empty()&&s1.top()!='(')
{
s.push_back(s1.top());
s1.pop();
}
s1.pop();
k=0;
}
}
while(!s1.empty())
{
s.push_back(s1.top());s1.pop();
}
cout<<s;
}