I'm running into an error with my prefix expression evaluator.
The error that I get when I try to run it is
Expression (+ (- 6) (* 2 3 4) (/ (+ 3) (- 2 3 1)))
Expression in thread "main" java.lang.NumberFormatException: For input string: "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatException: For input string "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
//code starts here
import java.util.*;
public class SimpleLispExpressionEvaluator {
// Current input Lisp expression
private String inputExpr;
// Main stack & temp stack, see algorithm in evaluate()
private Stack<Object> expressionStack;
private Stack<Double> tempStack;
// default constructor
// set inputExpr to ""
// create stack objects
public SimpleLispExpressionEvaluator()
{
inputExpr = "";
expressionStack = new Stack<Object>();
tempStack = new Stack<Double>();
}
// default constructor
// set inputExpr to inputExpression
// create stack objects
public SimpleLispExpressionEvaluator(String inputExpression)
{
inputExpr = inputExpression;
expressionStack = new Stack<Object>();
tempStack = new Stack<Double>();
}
// set inputExpr to inputExpression
// clear stack objects
public void reset(String inputExpression)
{
inputExpr = inputExpression;
Stack<Object> expressionStack = new Stack<Object>();
Stack<Double> tempstack = new Stack<Double>();
}
private boolean checkifNumber() {
return false;
}
// This function evaluate current operator with its operands
// See complete algorithm in evaluate()
//
// Main Steps:
// Pop operands from expressionStack and push them onto
// tempStack until you find an operator
// Apply the operator to the operands on tempStack
// Push the result into expressionStack
//
`private double add() {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 + op2;
return temp;
}`
private double multiply() {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 * op2;
return temp;
}
private double subtract() {
if (tempStack.size() == 1) {
double temp = -tempStack.pop();
return temp;
} else {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 - op2;
return temp;
}
}
private double divide() {
if (tempStack.size() == 1) {
double temp = 1 / tempStack.pop();
return temp;
} else if (tempStack.pop() == 0 || tempStack.pop() == null) {
throw new IndexOutOfBoundsException(); } else {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 - op2;
return temp;
}
}
private void evaluateCurrentOperation()
{
while( expressionStack.peek().getClass().getName().equals("java.lang.Double") ) {
tempStack.push( (Double)expressionStack.pop() );
}
Character operator = (Character)expressionStack.pop();
Double result = null;
switch( operator ) {
case '+':
result = add();
break;
case '*':
result = multiply();
break;
case '-':
result = subtract();
break;
case '/':
result = divide();
break;
}
expressionStack.push( result );
}
/**
* This function evaluates Lisp expression in inputExpr
* It return result of the expression
*
* The algorithm:
*
* Step 1 Scan the tokens in the expression string.
* Step 2 If you see an operand, push operand object onto the expressionStack
* Step 3 If you see "(", next token should be an operator
* Step 4 If you see an operator, push operator object onto the expressionStack
* Step 5 If you see ")" // steps in evaluateCurrentOperation() :
* Step 6 Pop operands and push them onto tempStack
* until you find an operator
* Step 7 Apply the operator to the operands on tempStack
* Step 8 Push the result into expressionStack
* Step 9 If you run out of tokens, the value on the top of expressionStack is
* is the result of the expression.
*/
public double evaluate()
{
// only outline is given...
// you need to add statements
// you may delete or modify any statements in this method
// use scanner to tokenize inputExpr
Scanner inputExprScanner = new Scanner(inputExpr);
// Use zero or more white space as delimiter,
// which breaks the string into single character tokens
inputExprScanner = inputExprScanner.useDelimiter("\\s*");
// Step 1: Scan the tokens in the string.
while (inputExprScanner.hasNext())
{
// Step 2: If you see an operand, push operand object onto the expressionStack
if (inputExprScanner.hasNextInt())
{
// This force scanner to grab all of the digits
// Otherwise, it will just get one char
String dataString = inputExprScanner.findInLine("\\d+");
expressionStack.push(new Double(dataString));
// more ...
}
else
{
// Get next token, only one char in string token
String aToken = inputExprScanner.next();
char item = aToken.charAt(0);
String nextToken;
char nextItem;
switch (item)
{
// Step 3: If you see "(", next token should be an operator
case '(':
nextToken = inputExprScanner.next();
nextItem = nextToken.charAt(0);
// Step 4: If you see an operator, push operator object onto the expressionStack
if (nextItem == '+') {
expressionStack.push(nextItem);
} else if (nextItem == '-') {
expressionStack.push(nextItem);
} else if (nextItem == '*') {
expressionStack.push(nextItem);
} else {
expressionStack.push(nextItem);
}
break;
// Step 5: If you see ")" // steps 6,7,8 in evaluateCurrentOperation()
case ')':
try {
evaluateCurrentOperation();
} catch (EmptyStackException e) {
break;
}
break;
default: // error
throw new RuntimeException(item + " is not a legal expression operator");
} // end switch
} // end else
} // end while
// Step 9: If you run out of tokens, the value on the top of expressionStack is
// is the result of the expression.
//
// return result
double result = new Double(inputExpr);
return result;
}
// This static method is used by main() only
private static void evaluateExprt(String s, SimpleLispExpressionEvaluator expr)
{
Double result;
System.out.println("Expression " + s);
expr.reset(s);
result = expr.evaluate();
System.out.printf("Result %.2f\n", result);
System.out.println("-----------------------------");
}
// simple tests
public static void main (String args[])
{
SimpleLispExpressionEvaluator expr= new SimpleLispExpressionEvaluator();
String test1 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))";
String test2 = "(+ (- 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)))";
String test3 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 1) (- 2 1 )))";
String test4 = "(+ (/2))";
String test5 = "(+ (/2 3 0))";
String test6 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 3) (- 2 1 ))))";
evaluateExprt(test1, expr);
evaluateExprt(test2, expr);
evaluateExprt(test3, expr);
evaluateExprt(test4, expr);
evaluateExprt(test5, expr);
evaluateExprt(test6, expr);
} }
Step 9 of evaluate is not doing what is commented:
// Step 9: If you run out of tokens, the value on the top of expressionStack is
// is the result of the expression.
//
// return result
double result = new Double(inputExpr);
it is trying to convert the whole input string into a double, not retrieving the top of the expression stack. It should be something like
double result = (Double)expressionStack.pop();
also beware that the operators, as implemented, do not accept 3 or more arguments - (* 2 3 4) should not work.
Related
If i have this string infix expression 2*4+3-15/2 and i want as output the postfix expression without considering the priority of the operations like so
2 4 * 3 + 15 - 2 /
What modifications do i need to in this code sample to "remove" that priority. I took this code from geeksforgeeks here https://www.geeksforgeeks.org/stack-set-2-infix-to-postfix/. I find it a little difficult to change to meet what i want. Where should i start? thanks.
the current code gives me this output : 24*3+152/-
private int Prec(String ch)
{
switch (ch)
{
case "+":
case "-":
return 1;
case "*":
case "/":
return 2;
case "^":
return 3;
}
return -1;
}
private boolean isNumeric(String strNum) {
if (strNum == null) {
return false;
}
try {
double d = Double.parseDouble(strNum);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
private String infixToPostfix(String infixExpression){
// initializing empty String for result
StringBuilder postfixExpression = new StringBuilder(new String(""));
String[] infixExp = infixExpression.split(" ");
// initializing empty stack
Stack<String> stack = new Stack<>();
for (String token : infixExp) {
System.out.println(token+" ");
// If the scanned character is an operand, add it to output.
if (isNumeric(token))
postfixExpression.append(token);
// If the scanned character is an '(', push it to the stack.
else if (token.equals("("))
stack.push(token);
// If the scanned character is an ')', pop and output from the stack
// until an '(' is encountered.
else if (token.equals(")")) {
while (!stack.isEmpty() && !stack.peek().equals("("))
postfixExpression.append(stack.pop());
if (!stack.isEmpty() && !stack.peek().equals("("))
return "Invalid Expression"; // invalid expression
else
stack.pop();
} else // an operator is encountered
{
while (!stack.isEmpty() && Prec(token) <= Prec(stack.peek())) {
if (stack.peek().equals("("))
return "Invalid Expression";
postfixExpression.append(stack.pop());
}
stack.push(token);
}
}
// pop all the operators from the stack
while (!stack.isEmpty()){
if(stack.peek().equals("("))
return "Invalid Expression";
postfixExpression.append(stack.pop());
}
System.out.println(postfixExpression);
return postfixExpression.toString();
}
It seems you just need to reverse the order of each pair formed by an operator and a number. You could do this using regular expressions and replaceAll:
String infix = "2*4+3-15/2";
String postfix = infix.replaceAll("([*+-/])([0-9]+)", " $2 $1");
System.out.println(postfix);
Output:
2 4 * 3 + 15 - 2 /
I'm pretty lost at the moment on how I would go about implementing this Tree, I'm trying to construct a Tree from a string representation of input "(4 + 6) + (2 + 3)". How would I go about making a Tree from two Stacks?
public class Tree {
private Stack opStk = new Stack();
private Stack valStk = new Stack();
private Tree parent = null;
public Tree(String str){
System.out.println((EvaluateExpression(str)));
}
public void doOperation() {
Object x = valStk.pop();
Object y = valStk.pop();
Object op = opStk.pop();
if ((Integer) x <= 0 || (Integer) y <= 0){
throw new NumberFormatException();
}
if (op.equals("+")) {
int sum = (Integer) x + (Integer) y;
valStk.push(sum);
}
}
public void repeatOps(char refOp) {
while (valStk.count() > 1 &&
prec(refOp) <= prec((char)opStk.pop())) {
doOperation();
}
}
int prec(char op) {
switch (op) {
case '+':
case '-':
return 0;
case '*':
case '/':
return 1;
case '^':
return 2;
default:
throw new IllegalArgumentException("Operator unknown: " + op);
}
}
public Object EvaluateExpression(String str) {
System.out.println("Evaluating " + str);
Scanner s = null;
try {
s = new Scanner(str);
//while there is tokens to be read
while (s.hasNext()) {
//if token is an int
if (s.hasNextInt()) {
//read it
int val = s.nextInt();
if(val <= 0) {
throw new NumberFormatException("Non-positive");
}
System.out.println("Val " + val);
//push it to the stack
valStk.push(val);
} else {
//push operator
String next = s.next();
char chr = next.charAt(0);
System.out.println("Repeat Ops " + chr);
repeatOps(chr);
System.out.println("Op " + next);
opStk.push(chr);
}
repeatOps('+');
}
} finally {
if (s != null) {
s.close();
}
}
System.out.println("Should be the result: " + valStk.pop());
return valStk.pop();
}
I have a few suggestions to make that might set you on the right path (hopefully).
Firstly I suggest your expression tree follow the Composite Design Pattern. It works very well for these types of hierarchies. For your purpose it would look something like:
interface Expression {
int getValue();
}
class Constant implements Expression {
private int value;
public int getValue() {
return value;
}
}
class Operation implements Expression {
private Expression operand1;
private Operator operator;
private Expression operand2;
public int getValue() {
return operator.apply(operand1, operand2);
}
}
Note that you don't need any concept of operator precedence or parentheses: it's entirely implicit in how the tree is constructed. For example "3 + 4 * 2" should result in a tree "(+ 3 (* 4 2))" while "(3 + 4) * 2" should result in a tree "(* (+ 3 4) 2)".
Secondly I suggest you make your operators into an enum rather than relying on the string values:
enum Operator {
TIMES((n1, n2) -> n1 * n2),
DIVIDE((n1, n2) -> n1 / n2),
PLUS((n1, n2) -> n1 + n2),
MINUS((n1, n2) -> n1 - n2);
private final BinaryOperator<Integer> operation;
Operator(BinaryOperator<Integer> operation) {
this.operation = operation;
}
public int apply(int operand1, int operand2) {
return operation.apply(operand1, operand2);
}
}
The advantage of this approach is that it's trivial to add new operators without changing the structure of the tree at all.
Thirdly I suggest you split your conversion from string to expression tree into two steps. The first is to convert from string to tokens and the second from token to trees. These are call lexical and semantic analysis in the jargon.
If you are using the shunting yard algorithm for the semantic analysis then keep in mind that the output stack will hold Expression instances ready to become operands. I can give you more detail on how to shunt operators but it's probably worth you giving the suggestions above a try first.
here is the code
I have a calculator class , right now it only accounts for numbers but im trying to get it to account for a variable and set the value of the variable to a specific number ie 5
sorry if i was unclear. when i run this calculator , and input 1+1 it gives me 2 as the answer. but i want to be able to include a varibable for example 3*x^2 or 3*y^2. with the value of the variable being 5. right now this code is unable to do that.
public class Calculator {
// Allowable mathematical operators
static final String operators = "+-*/%()^!";
private String strPostfix;
private String strInfix;
private char chrVariable;
private int intError;
/**
* Default constructor. Sets all local values to default values
*/
public Calculator() {
setEquation("");
}
/**
* Sets a new equation.
* #param equation The new equation.
* #remarks Note that this also resets all values stored same as creating a new object
*/
public void setEquation(String equation)
{
// Remove any spaces, as they aren't necessary
strInfix = equation.replace(" ", "").trim();
strPostfix = "";
chrVariable = '\0';
intError = -2;
}
/**
* Gets the character location of the error found. -1 means no error found.
* #return An integer specifying the location of the error.
*/
public int get_ErrorLocation()
{
return intError + 1;
}
/**
* Gets the operators being used
* #return The operators
*/
public String get_Operators()
{
return operators;
}
/**
* Gets the post fix equation stored in memory for this object
* #return A post fix equation stored in a string
*/
public String get_PostFix()
{
return strPostfix;
}
/**
* Gets the variable that is in the equation. '~' means no variable found.
* #return The variable being used in the equation.
*/
public char get_Variable()
{
return chrVariable;
}
/**
* Solves the equation stored in memory for this instance, and stores it in memory
* #return A solution to a pre-existing equation
* #throws NoEquationException Occurs when attempting to solve an equation that doesn't exist
* #throws DivisionByZeroException Thrown when attempting to divide by zero
* #throws InvalidEquationException Occurs if an equation is invalid for an undefined reason
* #throws ExistingVariableException Occurs when attempting to use two variables
* #throws InvalidCharacterException Occurs when an invalid character is entered
*/
public double Solve() throws NoEquationException, DivisionByZeroException, InvalidEquationException, InvalidCharacterException, ExistingVariableException
{
strPostfix = PostFix().trim();
System.out.println(strPostfix);
return SolvePost();
}
/**
* Determines the precendence of a give mathematical operator
* #param value The mathematical operator
* #return The precendence of the operator
*/
private short precedence(char value) {
switch (value) {
case '+':
case '-':
return 1;
case '*':
case '/':
case '%':
return 2;
case '!':
return 3;
case '^':
return 4;
default:
return -1;
}
}
/**
* Turns an infix equation into post-fix
* #return The post-fix equivalent of the equation
* #throws InvalidEquationException When an invalid equation is given
* #throws ExistingVariableException Occurs when attempting to use two variables
* #throws InvalidCharacterException Occurs when an invalid character is entered
* #throws NoEquationException Occurs when attempting to solve an equation that doesn't exist
*/
private String PostFix() throws InvalidEquationException, InvalidCharacterException, ExistingVariableException {
// Backup the equation
String infix = strInfix;
String postfix = "";
char current;
char chrVariable;
Stack<Character> stack = new Stack<Character>();
boolean hasDec = false;
// For every character in the string
for ( int idx = 0; idx < infix.length(); ++idx ) {
current = infix.charAt(idx);
// If it is a digit or letter , just add it to postfix
if ( Character.isDigit(current) ) {
postfix += current;
// If it is a decimal, make sure there is only one per number
}else if (Character.isLetter(current))
postfix+=current;
else if( current == '.' ) {
if (!hasDec)
postfix += String.valueOf(current);
else
throw new InvalidEquationException();
hasDec = true;
// Otherwise, its an operator
}
else {
postfix += " ";
hasDec = false;
char peek;
// If there's an opening brace, just push it to the stack
if ( current == '(' )
stack.push(current);
// If its a closing brace, find pop until you find the opening one
else if ( current == ')' ) {
while ( !stack.isEmpty() && stack.peek() != '(' ) {
postfix += stack.pop() + " ";
}
// If the stack is empty, '(' was not found, error
if (stack.isEmpty()) { throw new InvalidEquationException('('); }
// Remove the '(' from the list
stack.pop();
} else {
if ( current == '-' && ( idx == 0 || operators.contains(String.valueOf(infix.charAt(idx - 1))))) {
postfix += current;
} else {
short prec = precedence(current);
if ( prec == -1 ) {
intError = idx;
throw new InvalidCharacterException();
}
// Pop off everything that has greater or equal precedence
if ( !stack.isEmpty() ) {
peek = stack.peek();
while ( precedence(current) <= precedence(peek) ) {
postfix += stack.pop() + " ";
if ( !stack.isEmpty() )
peek = stack.peek();
else
break;
}
}
// Now add the current onto the stack
stack.push(current);
}
}
}
}
// Finally, empty out the stack
while ( !stack.isEmpty() ) {
postfix += " " + stack.pop();
}
postfix = postfix.trim();
while ( postfix.contains(" ") ) {
postfix = postfix.replaceAll(" ", " ");
}
return postfix;
}
/**
* Solves the post-fix equation
* #return The solution to the equation
* #throws NoEquationException Thrown when PostFix equation not set
* #throws DivisionByZeroException Thrown when attempting to divide by zero
* #throws InvalidEquationException When an invalid equation is given
*/
private double SolvePost() throws NoEquationException, DivisionByZeroException, InvalidEquationException {
// Make sure there is an equation to solve
if ( strPostfix.trim().isEmpty() )
throw new NoEquationException();
Stack<Double> stack = new Stack<Double>();
String tokens[] = strPostfix.split(" ");
for ( String current : tokens ) {
try {
// If its a number, just push it
stack.push(Double.parseDouble(current));
} catch (Exception e) {
// If its not an operator, there's a problem
if ( current.length() > 1 || !operators.contains(current) )
throw new InvalidEquationException();
// there must be two operands, otherwise there's a problem
double first = 0, second = 0;
try {
second = stack.pop();
if ( current.charAt(0) != '!' )
first = stack.pop();
} catch (Exception ex) {
throw new InvalidEquationException();
}
// Do the appropriate math
switch ( current.charAt(0) ) {
case '+':
stack.push(first + second);
break;
case '-':
stack.push(first - second);
break;
case '*':
stack.push(first * second);
break;
case '/':
// Make sure its not division by zero
if (second == 0) { throw new DivisionByZeroException(); }
stack.push(first / second);
break;
case '%':
stack.push(first % second);
break;
case '^':
stack.push(Math.pow(first, second));
break;
case '!':
if ( (int)second != second || second < 0 )
throw new InvalidEquationException();
int result = 1;
for ( int i = 2; i <= second; ++i )
result *= i;
stack.push((double)result);
break;
default:
// Anything else isn't valid
throw new InvalidEquationException();
}
}
}
return stack.pop();
}
}
Bear with me, I'm a little fried right now from getting this all together, but I'm at the final stretch. I've made a calculator in java that takes an infix equation and then changes it to postfix. It also takes variables! I'm made it so my postfix includes negative numbers from infix. This would look like so:
infix: 1+-2*(4/2)
postfix: 12_42/*+
So obviously I got it working where negatives are '_' in postfix. Cool yeah? Ok, but now I gotta get my calculator to read them and I'm just getting brain-fart on where it goes on the stack and what I do to make it work without making a condition for all forms of operands. Here is what I have:
import java.util.Stack;
/**
*
* #author rtibbetts268
*/
public class InfixToPostfix
{
/**
* Operators in reverse order of precedence.
*/
private static final String operators = "-+/*_";
private static final String operands = "0123456789x";
/*public int evalInfix(String infix)
{
return evaluatePostfix(convert2Postfix(infix));
}*/
public String xToValue(String postfixExpr, String x)
{
char[] chars = postfixExpr.toCharArray();
StringBuilder newPostfixExpr = new StringBuilder();
for (char c : chars)
{
if (c == 'x')
{
newPostfixExpr.append(x);
}
else
{
newPostfixExpr.append(c);
}
}
return newPostfixExpr.toString();
}
public String convert2Postfix(String infixExpr)
{
char[] chars = infixExpr.toCharArray();
StringBuilder in = new StringBuilder(infixExpr.length());
for (int i = 0; i<chars.length; i++)
{
if (infixExpr.charAt(i) == '-')
{
if (i == 0)
{
in.append('_');
}
else if(isOperand(infixExpr.charAt(i + 1)))
{
if (i != infixExpr.length())
{
if (isOperator(infixExpr.charAt(i-1)))
in.append('_');
}
else
{
in.append(infixExpr.charAt(i));
}
}
else
{
in.append(infixExpr.charAt(i));
}
}
else
{
in.append(infixExpr.charAt(i));
}
}
chars = in.toString().toCharArray();
Stack<Character> stack = new Stack<Character>();
StringBuilder out = new StringBuilder(in.toString().length());
for (char c : chars)
{
if (isOperator(c))
{
while (!stack.isEmpty() && stack.peek() != '(')
{
if (operatorGreaterOrEqual(stack.peek(), c))
{
out.append(stack.pop());
}
else
{
break;
}
}
stack.push(c);
}
else if (c == '(')
{
stack.push(c);
}
else if (c == ')')
{
while (!stack.isEmpty() && stack.peek() != '(')
{
out.append(stack.pop());
}
if (!stack.isEmpty())
{
stack.pop();
}
}
else if (isOperand(c))
{
out.append(c);
}
}
while (!stack.empty())
{
out.append(stack.pop());
}
return out.toString();
}
public int evaluatePostfix(String postfixExpr)//YBEYFCNUNKJKDV IT'S RIGHT HERE!!!
{
char[] chars = postfixExpr.toCharArray();
Stack<Integer> stack = new Stack<Integer>();
for (char c : chars)
{
if (isOperand(c))
{
stack.push(c - '0'); // convert char to int val
}
else if (isOperator(c))
{
int op1 = stack.pop();
int op2 = stack.pop();
int result;
switch (c) {
case '_':
result = op1 * -1;
//stack.push(result);
//break;
case '*':
result = op1 * op2;
stack.push(result);
break;
case '/':
result = op2 / op1;
stack.push(result);
break;
case '+':
result = op1 + op2;
stack.push(result);
break;
case '-':
result = op2 - op1;
stack.push(result);
break;
}
}
}
return stack.pop();
}
private int getPrecedence(char operator)
{
int ret = 0;
if (operator == '-' || operator == '+')
{
ret = 1;
}
else if (operator == '*' || operator == '/')
{
ret = 2;
}
if (operator == '_')
{
ret = 3;
}
return ret;
}
private boolean operatorGreaterOrEqual(char op1, char op2)
{
return getPrecedence(op1) >= getPrecedence(op2);
}
private boolean isOperator(char val)
{
return operators.indexOf(val) >= 0;
}
private boolean isOperand(char val)
{
return operands.indexOf(val) >= 0;
}
}
I would post less, but it all tends to work cohesively so I'll explain. Look closely at the method called evaluatePostfix() (it's the third one from the top).
This is where the class can take a postfix expression such as the one I named above and calculates it. It calculates an expression with all positive integers, but when I tried to implement it to change a number to negative before it actually ran any of the math, it goes kaputt.
Could anyone assist me with fixing this specific method so it works? I need it to calculate negative integers as well of positive.
Basically the problem is in trying to pop from an empty stack for the '_' case. What you need to do is only attempt to pop op2 from the stack for the '*/+-' cases and not the '_' case.
public int evaluatePostfix(String postfixExpr)
{
char[] chars = postfixExpr.toCharArray();
Stack<Integer> stack = new Stack<Integer>();
for (char c : chars)
{
if (isOperand(c))
{
stack.push(c - '0'); // convert char to int val
}
else if (isOperator(c))
{
int op1 = stack.pop();
int op2;
int result;
switch (c) {
case '_':
result = op1 * -1;
stack.push(result);
break;
case '*':
op2 = stack.pop();
result = op1 * op2;
stack.push(result);
break;
case '/':
op2 = stack.pop();
result = op2 / op1;
stack.push(result);
break;
case '+':
op2 = stack.pop();
result = op1 + op2;
stack.push(result);
break;
case '-':
op2 = stack.pop();
result = op2 - op1;
stack.push(result);
break;
}
}
}
return stack.pop();
}
I'm having trouble implementing a stack as an array in java. When I try to utilize the array, I get nullPointerExceptions. I know that the rest of my code works because I'm able to run the program using the linked list implementation of the stack I have created. The code is below:
Edit: The stack trace is
Exception in thread "main" java.lang.NullPointerException
at LispEvaluator.evaluate(LispEvaluator.java:238)
at LispEvaluator.fileLoader(LispEvaluator.java:67)
at Driver.main(Driver.java:16)
Here is the code for the lispEvaluator class
//code starts here
import java.util.*;
import java.io.*;
public class LispEvaluator {
// Current input Lisp expression
private String inputExpr;
private Scanner sc;
private StackList exprStack;
private StackList tempStack;
// default constructor
// set inputExpr to ""
// create stack objects
public LispEvaluator()
{
inputExpr = "";
}
// default constructor
// set inputExpr to inputExpression
// create stack objects
public LispEvaluator(String inputExpression)
{
inputExpr = inputExpression;
}
// set inputExpr to inputExpression
// clear stack objects
public void reset(String inputExpression)
{
inputExpr = inputExpression;
StackList exprStack=new StackList(50);
StackList tempStack=new StackList(50);
}
private boolean checkifNumber() {
return false;
}
public void fileLoader(String mode,String file){
//Validate the user entered mode
if(mode.equals("0")){
exprStack=new StackList(50);
tempStack=new StackList(50);}
else{
ArrayStack exprStack=new ArrayStack(50);
ArrayStack tempStack=new ArrayStack(50);
}
try{
//Try to read the array from file
sc = new Scanner(new File(file));
while (sc.hasNextLine()) {
double result=0;
inputExpr=sc.nextLine();
reset(inputExpr);
result=evaluate();
System.out.println(result);
}
}
catch (FileNotFoundException e){
System.out.println("Cannot find requested input file");
}
catch(IOException io){
System.out.println("General file io error occured. Try again");
}
}
// This function evaluate current operator with its operands
// See complete algorithm in evaluate()
//
// Main Steps:
// Pop operands from expressionStack and push them onto
// tempStack until you find an operator
// Apply the operator to the operands on tempStack
// Push the result into expressionStack
//
private double add() {
double op1 = (Double) tempStack.pop();
double temp=op1;
while (tempStack.size()>0){
double op2 = (Double) tempStack.pop();
temp = temp + op2;}
return temp;
}
private double multiply() {
double op1 = (Double) tempStack.pop();
double temp=op1;
while (tempStack.size()>0){
double op2 = (Double) tempStack.pop();
temp = temp * op2;}
return temp;
}
private double subtract() {
if (tempStack.size() == 1) {
double temp = -1*(Double) tempStack.pop();
return temp;
} else {
double op1 = (Double) tempStack.pop();
double temp=op1;
while (tempStack.size()>0){
double op2 = (Double) tempStack.pop();
temp = temp - op2;}
return temp;
}
}
private double divide() {
double temp;
if (tempStack.size() == 1) {
temp = 1 / (Double) tempStack.pop();
return temp;
}
else if (tempStack.size() >=1) {
double op1 = (Double) tempStack.pop();
temp=op1;
while (tempStack.size()>0){
double op2 = (Double) tempStack.pop();
temp = temp / op2;}
return temp;
}
return 0;
}
private void evaluateCurrentOperation()
{
while( exprStack.top().getClass().getName().equals("java.lang.Double") ) {
tempStack.push( (Double)exprStack.pop() );
}
Character operator = (Character)exprStack.pop();
Double result = null;
switch( operator ) {
case '+':
result = add();
break;
case '*':
result = multiply();
break;
case '-':
result = subtract();
break;
case '/':
result = divide();
break;
}
exprStack.push( result );
}
/**
* This function evaluates Lisp expression in inputExpr
* It return result of the expression
*
* The algorithm:
*
* Step 1 Scan the tokens in the expression string.
* Step 2 If you see an operand, push operand object onto the expressionStack
* Step 3 If you see "(", next token should be an operator
* Step 4 If you see an operator, push operator object onto the expressionStack
* Step 5 If you see ")" // steps in evaluateCurrentOperation() :
* Step 6 Pop operands and push them onto tempStack
* until you find an operator
* Step 7 Apply the operator to the operands on tempStack
* Step 8 Push the result into expressionStack
* Step 9 If you run out of tokens, the value on the top of expressionStack is
* is the result of the expression.
*/
public double evaluate()
{
// only outline is given...
// you need to add statements
// you may delete or modify any statements in this method
// use scanner to tokenize inputExpr
Scanner inputExprScanner = new Scanner(inputExpr);
// Use zero or more white space as delimiter,
// which breaks the string into single character tokens
inputExprScanner = inputExprScanner.useDelimiter("\\s*");
// Step 1: Scan the tokens in the string.
while (inputExprScanner.hasNext())
{
// Step 2: If you see an operand, push operand object onto the expressionStack
if (inputExprScanner.hasNextInt())
{
// This force scanner to grab all of the digits
// Otherwise, it will just get one char
String dataString = inputExprScanner.findInLine("\\d+");
exprStack.push(new Double(dataString));
// more ...
}
else
{
// Get next token, only one char in string token
String aToken = inputExprScanner.next();
char item = aToken.charAt(0);
String nextToken;
char nextItem;
switch (item)
{
// Step 3: If you see "(", next token should be an operator
case '(':
nextToken = inputExprScanner.next();
nextItem = nextToken.charAt(0);
// Step 4: If you see an operator, push operator object onto the expressionStack
if (nextItem == '+') {
exprStack.push(nextItem);
} else if (nextItem == '-') {
exprStack.push(nextItem);
} else if (nextItem == '*') {
exprStack.push(nextItem);
}else if (nextItem == '/'){
exprStack.push(nextItem);
}
else {
exprStack.push(nextItem);
}
break;
// Step 5: If you see ")" // steps 6,7,8 in evaluateCurrentOperation()
case ')':
try {
evaluateCurrentOperation();
} catch (EmptyStackException e) {
break;
}
break;
default: // error
throw new RuntimeException(item + " is not a legal expression operator");
} // end switch
} // end else
} // end while
// Step 9: If you run out of tokens, the value on the top of expressionStack is
// is the result of the expression.
//
// return result
double result = (Double) exprStack.pop();
return result;
}
}
/*
// This static method is used by main() only
private static void evaluateExprt(String s, SimpleLispExpressionEvaluator expr)
{
Double result;
System.out.println("Expression " + s);
expr.reset(s);
result = expr.evaluate();
System.out.printf("Result %.2f\n", result);
System.out.println("-----------------------------");
}
// simple tests
public static void main (String args[])
{
SimpleLispExpressionEvaluator expr= new SimpleLispExpressionEvaluator();
String test1 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))";
String test2 = "(+ (- 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)))";
String test3 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 1) (- 2 1 )))";
String test4 = "(+ (/2))";
String test5 = "(+ (/2 3 0))";
String test6 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 3) (- 2 1 ))))";
evaluateExprt(test1, expr);
evaluateExprt(test2, expr);
evaluateExprt(test3, expr);
evaluateExprt(test4, expr);
evaluateExprt(test5, expr);
evaluateExprt(test6, expr);
} }
*/
And heres the Array Stack:
public class ArrayStack implements BoundedStack
{
private int top;
private Object stk[];
private int size;
private int capacity;
public ArrayStack(){
top=-1;
capacity=50;
stk=new Object[capacity];
}
public ArrayStack(int cap)
{
top=-1;
size=0;
capacity=cap;
stk=new Object[capacity];
}
public void push(Object item) throws FullStackException
{
if(isFull()){
throw new FullStackException("The stack is full. Cannot push more elements onto the stack");}
else
{
stk[++top]=item;
}
}
public Object pop() throws EmptyStackException
{
if(isEmpty()==true)
{
throw new EmptyStackException("The stack is empty. Cannot pop another element from the stack");
}
else{
Object e=stk[top];
stk [top]=null;
--top;
return e;
}
}
public Object top() throws EmptyStackException{
if(isEmpty()==true){
throw new EmptyStackException("The stack is empty. Thus, it has no top");
}
return stk[top];
}
public int size(){
return (top+1);
}
public boolean isFull(){
if (size()==capacity){
return true;}
return false;
}
public boolean isEmpty(){
if(size()==0){
return true;}
return false;
}
public int capacity(){
return capacity;
}
}
The most obvious reason for this is you have not initialized your array elements before using it.
If you are creating an array like: -
SomeClass[] arr = new SomeClass[5];
Then before using your array, you need to initialize each array elements like this: -
for (int i = 0; i < arr.length; i++) {
arr[i] = new SomeClass();
}
If the line causing the NullPointerException is the line
exprStack.push(nextItem);
then the problem is not in the stack class. The problem is that exprStack is null (probably because it has never been assigned anything before this line).
You're making the same error as the following one several times in your code:
public void reset(String inputExpression) {
inputExpr = inputExpression;
StackList exprStack=new StackList(50);
StackList tempStack=new StackList(50);
}
The two last lines are completely useless: they assign a new StackList to a local variable. So the stack is created, and is immediately eligible to garbage collection, since nothing references it except a local variable that goes out of scope.
Here's another place where it happens:
if (mode.equals("0")){
exprStack=new StackList(50);
tempStack=new StackList(50);
}
else {
ArrayStack exprStack=new ArrayStack(50);
ArrayStack tempStack=new ArrayStack(50);
}