Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If else vs switch with stack logic

I'm learning about stacks by writing a program that validates bracket syntax. If I input (Baller) it should give me a positive result. If I have (Baller() it should give me a negative result. Essentially the application checks if the user has correctly used ( ) , { } and [].

  • If I encounter a ( , { , or [ character I will add it to the character on the stack.
  • If I encounter a ) } ] sign I will delete a character from the stack.
  • If the text contains an odd number of parentheses or brackets are not contiguous ( for example, ( and ] is not continuous ) , an error
    message is printed.

So I have done this half in a if else statement but I was thinking that it should be easier to make it in a switch statement and also be a good learning experience.

So what I have done in the switch statement is this:

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");
                }
            }
        }
    }
}

But now I'm getting a problem that if I just add a right side bracket it will just remove because I have a pop. I tried to make this in a if-else statement which will end in a if-statement like this:

if(first == '(' && (current == '}' || current == ']')) {
if first == '{' && (current == ']' || current == ')')) {
//and so on

How could I turn this into a switch case? Is this a bad idea?

What I know is there isn't really a problem on my left side bracket but there is on the right ones.

EDIT: HOW THE CODE LOOKS LIKE RIGHT NOW

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");
        }
    }
}
like image 797
Thrillofit123 Avatar asked Feb 10 '23 02:02

Thrillofit123


2 Answers

Good question! It's good that you already have a workable solution and are trying to improve on it.

You can still use your switch statement, but you first need to verify that your stack isn't empty before you attempt to pop the next value. In my implementation, I'm doing that check first by checking stack.isEmpty() and using a short-circuiting OR condition ||. Short-circuiting means that if the left side of an OR condition is true, then the right side will not even be evaluated.

This is the updated for loop. I'm not sure which Stack class you're using, so mine is using 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;
    }
}

EDIT: I added missing break; statements. Without these, the system will execute multiple case: conditions because it will 'fall through' to each one.

EDIT 2: Zong Zheng Li makes a good point in their answer. You should verify that there aren't any left over characters on the stack when you're done. After your loop, you should have something like this:

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

EDIT 3: Changed stack.firstElement() to stack.peek().

like image 106
Ben M. Avatar answered Feb 11 '23 14:02

Ben M.


Aside from checking whether specific characters match up, there are two cases where you need information about the stack itself:

  1. When the number of brackets don't much up in an intermediate state. This happens when you try to pop when the stack is empty.

  2. When there are orphaned brackets at the end of string. In this case the stack ends up non-empty.

To fix 1, you should check that the stack is not empty before popping:

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

or equivalently,

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

To fix 2, at end of your program, you should check the stack is empty. This catches the (bal)ler) case that has not been addressed.

if (!stack.empty()) 
    System.out.println("  Syntax ERROR");
}
like image 20
Zong Avatar answered Feb 11 '23 15:02

Zong