Java If-else vs带堆栈逻辑的交换机

Java If-else vs带堆栈逻辑的交换机,java,if-statement,stack,switch-statement,Java,If Statement,Stack,Switch Statement,我通过编写一个验证括号语法的程序来学习堆栈。如果我输入(Baller),它会给我一个肯定的结果。如果我有(Baller(),它应该会给我一个否定的结果。实际上,应用程序会检查用户是否正确使用了()、{}和[] 如果遇到(、{或[字符,我会将其添加到 堆栈上的字符 如果遇到)}]符号,我将从堆栈中删除一个字符 如果文本包含奇数个括号或方括号,则不显示 连续的(例如,(和)不是连续的),错误 消息已打印出来 因此,我在if-else语句中完成了这一半,但我认为在switch语句中完成这一半应该更

我通过编写一个验证括号语法的程序来学习堆栈。如果我输入
(Baller)
,它会给我一个肯定的结果。如果我有
(Baller()
,它应该会给我一个否定的结果。实际上,应用程序会检查用户是否正确使用了()、{}和[]

  • 如果遇到(、{或[字符,我会将其添加到 堆栈上的字符
  • 如果遇到)}]符号,我将从堆栈中删除一个字符
  • 如果文本包含奇数个括号或方括号,则不显示 连续的(例如,(和)不是连续的),错误
    消息已打印出来
因此,我在if-else语句中完成了这一半,但我认为在switch语句中完成这一半应该更容易,同时也是一次很好的学习体验

我在switch语句中所做的是:

public class Input {
    public static void main(String[] args) {
        Stack stack = new Stack();
        String str;
        str = JOptionPane.showInputDialog("Text to parse: ");
        char arr[] = str.toCharArray();
        System.out.print(str);
        System.out.println();
        System.out.println();

        for(char c : arr) {
            switch(c) {

            case '{':
                stack.Push(c);
                System.out.print(stack.firstNode.getData());
                break;
            case '(':
                stack.Push(c);
                System.out.print(stack.firstNode.getData());
                break;
            case '[':
                stack.Push(c);
                System.out.print(stack.firstNode.getData());
                break;

            case '}':
                c = (Character) stack.Peek(); //<-- Edited for @Jimmy
                if( c != '{') {
                    System.out.println("  Syntax ERROR");
                }
            case ']':
                if( c != '[') {
                    System.out.println("  Syntax ERROR");
                }   
            case ')':
                if( c != '(') {
                    System.out.println("  Syntax ERROR");
                }
            }
        }
    }
}
我怎么能把它变成开关箱?这是个坏主意吗

我所知道的是,我左边的支架没有问题,但右边的支架有问题

编辑:代码现在的样子

import javax.swing.JOptionPane;



public class Input {
    public static void main(String[] args) {
        Stack stack = new Stack();
        String str;
        str = JOptionPane.showInputDialog("Text to parse: ");
        char arr[] = str.toCharArray();
        System.out.print(str);
        System.out.println();
        System.out.println();


        for(char c : arr) {

            switch(c) {

            case '{':
                stack.Push(c);
                break;
            case '(':
                stack.Push(c);
                break;
            case '[':
                stack.Push(c);
                break;

            case '}':
                if(stack.isEmpty() || (Character) stack.Pop() != '{') {
                    System.out.println("  Syntax ERROR");
                }
                break;
            case ']':
                if(stack.isEmpty() || (Character) stack.Pop() != '[') {
                    System.out.println("  Syntax ERROR");
                }
                break;
            case ')':
                if(stack.isEmpty() || (Character) stack.Pop() != '(') {
                    System.out.println("  Syntax ERROR");
                }
                break;
            }
        } if(!stack.isEmpty()) {
            System.out.println("  Syntax ERROR");
        }
    }
}

除了检查特定字符是否匹配外,还有两种情况需要有关堆栈本身的信息:

  • 当中间状态中括号的数量不多时。当堆栈为空时尝试弹出时会发生这种情况

  • 当字符串末尾有孤立括号时。在这种情况下,堆栈结束时为非空

  • 要修复1,应在弹出前检查堆栈是否为空:

    case '}':
        if (stack.empty()) {
            System.out.println("  Syntax ERROR");
        }
        else {
            c = (Character) stack.Pop();
            if( c != '{') {
                System.out.println("  Syntax ERROR");
            }
        }
        break;
    
    或同等地

    case '}':
        if (stack.empty() || ((Character)stack.Pop()) != '{') {
            System.out.println("  Syntax ERROR");
        }
        break;
    
    要修复2,在程序结束时,应检查堆栈是否为空。这将捕获尚未解决的
    (bal)ler)
    情况

    if (!stack.empty()) 
        System.out.println("  Syntax ERROR");
    }
    

    好问题!很好,你已经有了一个可行的解决方案,并且正在努力改进它

    您仍然可以使用switch语句,但在尝试弹出下一个值之前,首先需要验证堆栈是否为空。在我的实现中,我首先通过检查
    stack.isEmpty()来执行该检查
    和使用短路或条件
    |
    。短路意味着,如果OR条件的左侧为真,则甚至不会计算右侧

    这是更新的for循环。我不确定您使用的是哪个堆栈类,所以我使用的是
    java.util.Stack

    for(char c : arr) {
    
        switch(c) {
    
        case '{':
            stack.push(c);
            System.out.print(stack.peek());
            break;
        case '(':
            stack.push(c);
            System.out.print(stack.peek());
            break;
        case '[':
            stack.push(c);
            System.out.print(stack.peek());
            break;
    
        case '}':
            if(stack.isEmpty() || (Character) stack.pop() != '{') {
                System.out.println("  Syntax ERROR");
            }
            break;
        case ']':
            if(stack.isEmpty() || (Character) stack.pop() != '[') {
                System.out.println("  Syntax ERROR");
            }
            break;
        case ')':
            if(stack.isEmpty() || (Character) stack.pop() != '(') {
                System.out.println("  Syntax ERROR");
            }
            break;
        }
    }
    
    编辑:我添加了缺少的
    break;
    语句。如果没有这些语句,系统将执行多个
    case:
    条件,因为它将对每个条件“失效”

    编辑2:Zong Zheng Li在他们的回答中提出了一个很好的观点。完成后,您应该验证堆栈上没有任何剩余字符。循环后,您应该有如下内容:

    if(first == '(' && (current == '}' || current == ']')) {
    if first == '{' && (current == ']' || current == ')')) {
    //and so on
    
    if(!stack.isEmpty()) {
        System.out.println("  Syntax ERROR");
    }
    

    编辑3:将
    stack.firstElement()
    更改为
    stack.peek()

    您说过您想学习如何使用
    switch
    语句。您可以使用一个巧妙的技巧,称为“跌破”:


    您还可以使用预实现的类,它也是。

    您可以使用peek(),它只会让您看到堆栈的最后一个内容。如果没有错误,那么您可以调用pop()否则,不要调用pop,它将不会被删除。@Jimmy,你能举个例子说明它在代码中的工作方式吗?否则,你打算在哪里进行更改?在你的第一个删除案例中是这样的。例如,对于案例“}”,例如:
    c=(Character)stack.Peek();if(c!='{'){System.out.println(“语法错误”);}else stack.Pop();
    @Jimmy好的,所以我把它改为Peek()得到了同样的结果。我在编辑中做了更改,向您展示了它的编辑位置。我认为最干净的解决方案是避免失败,在每个
    案例中都有一个单独的弹出窗口。但是要注意空堆栈的情况。另外,您应该使用
    堆栈
    来消除不安全的强制转换。这看起来有点令人惊讶!Howev呃,是的。我创建了一个自己的类,在其中我用自己的Push、Pop、Peek和Count方法进行了初始化。这让我们知道我没有isEmpty方法。但是我想它几乎和我的Count()方法一样,因为它返回Count中的元素。所以如果我对它做了一些更改,它能帮上忙吗?@Thillofit123是的,你可以使用你的Count()方法方法,如果你想用0来做一个相等的检查,例如“代码>堆栈。”(=)0 = <代码>。你应该考虑创建你自己的代码> iSimple()/<代码>,因为它会让你的代码读起来更好(加上它通常是一个不重复你的好习惯)。{if(count==0){return true;}else{return false;}}}这样就足够了吗?@stritrofit123几乎完美!您可以将其简化为:
    public boolean isEmpty(){return count==0;}
    很好!哇哦!真的!我真的很感谢你在这里的时间Ben.M和其他人!就我所见,它很有效。现在我要尝试让它更酷,但正如我现在看到的。一切都变好了!我无话可说!!!!这看起来很好!我已经创建了一个自己的类,在这里我通过自己的推送、弹出、偷看来初始化它d Count方法。这让我们知道我没有一个isEmpty方法。但我猜它几乎和我的Count()相同方法,因为它返回计数中的元素。因此,如果我对它做了一些更改,它能帮上忙吗?因为如果我导入Java堆栈。它会给我一个错误,因为我已经用Pop、Push等创建了自己的类。使用自己的
    堆栈
    类完全可以,除非您计划将代码发布为库并在它的API中使用您自己的
    堆栈
    。您可以通过
    堆栈.count()==0
    检查堆栈是否为空,因此您不需要创建一个
    isEmpty()
    方法,这完全取决于您自己。行吗
    switch (c) {
        case '{':
        case '(':
        case '[':
            stack.Push(c);
            System.out.print(stack.firstNode.getData());
            break;
    
        case '}':
        case ']':
        case ')':
            if (stack.isEmpty() || stack.pop() != c) {
                System.out.println("Syntax ERROR");
            }
            break;
    }