tags:

views:

77

answers:

4

hi, i am not sure how can i read a number like 10 and above for a char array, i am converting from infix to postfix , currently i am able to do so for single digits however when it comes to multiple digits when evaluating the postfix equation it would be a wrong answer. for example 10+13+4 it would give a wrong answer but 1+3+4 it would be correct.

        //class main 
        calcParser calc = new calcParser("13+20+3+4");
               calc.toPostfix();
               calc.displayPostfix();
               calc.evaluatePostfix();
               calc.displayResult();
       // result for above would be
    1320+3+4+
    9.0

// class calcParser
      public void toPostfix()
        {
          for(char c : originalExp.toCharArray())
          {
              switch(c)
              {
                  case '0': case '1': case '2': case '3': case '4': case '5':
                  case '6': case '7': case '8': case '9':
                  postfixExp.append(c);
                  break;

                  case '+': case '-':
                  if(postfixStack.empty())
                  {
                      postfixStack.push(c);
                  }
                  else
                  {
                      if((postfixStack.peek().equals(c)))
                      {
                          postfixExp.append(postfixStack.pop());
                          postfixStack.push(c);
                      }
                      else
                      {
                          postfixExp.append(postfixStack.pop());
                          postfixStack.push(c);
                      }

                  }
                  break;
                }
            }
            while(!postfixStack.empty())
            {
             postfixExp.append(postfixStack.pop());
            }
          }

        public void evaluatePostfix()
        {
           String postfix = postfixExp.toString();
           for(char c : postfix.toCharArray())
           {
               switch (c)
               {
                  case '0': case '1': case '2': case '3': case '4': case '5':
                  case '6': case '7': case '8': case '9':
                  postfixResultStack.push(c);
                  break;

                  case '+':
                  firstOperand = Double.parseDouble(postfixResultStack.pop().toString());
                   secondOperand = Double.parseDouble(postfixResultStack.pop().toString());
                  postfixResultStack.push(firstOperand + secondOperand);
                  break;

                  case '-':
                  firstOperand = Double.parseDouble(postfixResultStack.pop().toString());
                  secondOperand = Double.parseDouble(postfixResultStack.pop().toString());
                  postfixResultStack.push(firstOperand - secondOperand);
                  break;

               }

           }

        }
+3  A: 

Just scan while you keep getting digits. But you'll have to abandon the idea of using for (char : ...). You need a way to advance the current position explicitly.

EJP
+1 - that's a good enough hint for a homework problem.
Stephen C
so i will need to abandon the char[] too? since the char[] only take a literal it cannot read multiple digit as one.
kyrogue
That question doesn't make any sense to me.
EJP
sorry if i am not clear, you said to abandon the for each loop, does it mean i will also have to abandon converting the expression string into a char array too?
kyrogue
I didn't say so, and I don't understand what your reasons may be for thinking so.
EJP
+1  A: 

how about using a StringTokenizer? split the string using the operand as the token then use Integer.parseInt() to parse the numbers?

Ok i just come up with something that solves your homework. It's ugly but working. :)

public static void main(String[] args) {
    String expression = "10+10+2-10-1";
    List<String> positiveOperands = new ArrayList<String>();
    StringTokenizer st = new StringTokenizer(expression, "+");
    while(st.hasMoreElements()){
        positiveOperands.add(st.nextToken());
    }
    int total = 0;
    for(String posOperand: positiveOperands){
        // evaluate subtraction
        StringTokenizer st2 = new StringTokenizer(posOperand, "-");
        int a = 0;
        if(st2.hasMoreElements()) a = Integer.parseInt(st2.nextToken());
        while(st2.hasMoreElements()){
            a-=Integer.parseInt(st2.nextToken());
        }
        total+=a;
    }
    System.out.println(total);
}
demotics2002
`StringTokenizer` is legacy. At the very least use `Scanner`, or even `String.split` should be fine in this case.
polygenelubricants
given 10+1+3 what can i split on? since there is no whitespaces
kyrogue
thanks @poly. The split works like this... "10+1+3".split("\\+") and returns an array of strings {"10","1","3"} @kyrogue
demotics2002
yes, if i split on the operators then how can i retrieve it back? and convert it to postfix?
kyrogue
A: 

You probably want to work in terms of Token's not char's.

Have the first stage of your parser consume a stream of char's and generate a stream of Tokens, and then have the next stages generate/execute the stack.

So you have:

"10+11 + 4" becomes

List { Number(10), Operator(+), Number(11), Operator(+), Number(4) }

Then you use your existing toPostFix() (modified to work on tokens) build the stack, then print/evaluate/etc.

To generate the tokens the traditional approach is a series of regexes applied in order with the first match being used to generate a Token.

Recurse
A: 

Here's a solution that uses java.util.Scanner:

Scanner sc = new Scanner("12+3 - 456").useDelimiter("\\b");
while (sc.hasNext()) {
    if (sc.hasNextInt()) {
        int num = sc.nextInt();
        System.out.printf("Got an int [%s]%n", num);
    } else {
        String op = sc.next().trim();
        System.out.printf("Got an op [%s]%n", op);
    }
}

The above prints (as seen on ideone.com):

Got an int [12]
Got an op [+]
Got an int [3]
Got an op [-]
Got an int [456]

The delimiter is \b (the backslash doubled in a Java string literal), which is the "word boundary". It occurs, among other places, between word characters \w (which digits are) and non-word characters \W (which operators are).

As a caveat, this delimiter regex will not properly tokenize floating point numbers with decimal points, but more specific regex can be written to address those issues should they be needed.

Note also the convenience of using Scanner to parse the String into int; you can do this in such a way that it will never throw an exception (e.g. by first asserting that it hasNextInt()).

Related questions

References

polygenelubricants
thanks, the \w delimiter is what im looking at, however in the later stages if i were to implement it to include decimal points 10.5+20 would it be hard?
kyrogue
@kyrogue: Not hard at all if you know regex. You may have to use zero-width matching regex with assertions. See e.g. http://stackoverflow.com/questions/2406633/can-you-use-zero-width-matching-regex-in-string-split/2406862#2406862 , http://stackoverflow.com/questions/2819933/java-split-is-eating-my-characters/2820009#2820009 , etc.
polygenelubricants