0

The program is about asking the user to write an expression and then pushing the numbers into a stack. The data type of the expression must be string. I have started with the code, but the problem is that the program sees every digit as a seperate one. For example if I want the stack to push the number 30 it will push 3 then push 0. Is there any simple ways solving the problem?

enter code here

public class Main {
public static void main(String[] args) {
    String userInput = " (14 + 2 * 33)";
    System.out.println(evaluate(userInput));

}

public static int evaluate(String expression)
{
    char[] tokens = expression.toCharArray();

    Stack<Integer> values = new
                          Stack<Integer>();


    for (int i = 0; i < tokens.length; i++)
    {

        if (Character.isDigit(tokens[i])) {
              values.push(Integer.parseInt(String.valueOf(tokens[i])));

        }
Mo Pie
  • 41
  • 5
  • 2
    Please see the answers in [How to evaluate a math expression given in string form?](https://stackoverflow.com/questions/3422673/how-to-evaluate-a-math-expression-given-in-string-form) – Hovercraft Full Of Eels Sep 03 '22 at 22:17
  • `if (Character.isDigit(tokens[i]))` Obviously you need to do something different there. If you read a character, then push it immediately on the stack, of course you will get strings consisting of a single character (digit). You should have covered how to append characters to make a longer string, that should be your next step. – markspace Sep 03 '22 at 22:31

1 Answers1

1

The root of your problem is a conceptual one. Characters are not tokens. In formal grammar theory and practical parser implementation, a token is a sequence of one or more (input) characters that together represent an abstract symbol in your grammar.

So for example we would typically tokenize " (14 + 2 * 33)" as the following sequence of tokens:

 LPAREN <- "("
 NUMBER <- "14"
 PLUS   <- "+"
 NUMBER <- "2"
 STAR   <- "*"
 NUMBER <- "33"
 RPAREN <- ")"

Things to note:

  • We have gotten rid of the (non-significant) whitespace from the token stream
  • We have one token for each (complete) number, not to each digit.

Now we don't have to do either of those things. But if you have tokens for whitespace or for each digit in a number (or each character in an identifier or keyword) then the grammar (or parser) that builds on (or consumes) the token stream will be a lot more complicated and verbose.

So ... basically ...

for (int i = 0; i < tokens.length; i++) {
    if (Character.isDigit(tokens[i])) {
          values.push(Integer.parseInt(String.valueOf(tokens[i])));
    }
}

is wrong. You need to skip whitespace, combine sequences of digits into a single token and NOT discard the characters that represent the operators and brackets in the expression. And calling the input array tokens is misleading ...

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Okay so I added the "We have gotten rid of the (non-significant) whitespace from the token stream". My simple question is: how "We have one token for each (complete) number, not to each digit"? . The reason why I dont get it is because the data type is of char so how do I comine sequences of digites into a single one? – Mo Pie Sep 04 '22 at 07:42
  • Use a `StringBuilder` and it's `append(char)` and `toString()` methods to build a string consisting of digits. Read the `javadoc` for details ... work out the rest. – Stephen C Sep 04 '22 at 09:17