JAVA Оценка выражений postfix - невозможно выбросить пустые или недействительные выражения - PullRequest
0 голосов
/ 30 августа 2018

Я пишу программу, которая будет оценивать постфиксное выражение и печатать как оригинальное выражение, так и результат. Но я хочу объяснить и правильность выражения. Для этого я написал два класса исключений - один для пустой коллекции и один для недопустимых выражений постфикса. Но мой код где-то застрял; Мой вывод правильно оценивает первое выражение, но затем печатает только оригинальные выражения постфикса. Я полагаю, что проблема, возможно, исходит от моего класса PostfixEvaluator (см. Ниже), где я пытаюсь проверить размер моего стека в методе оценки. Когда закомментировано, мои постфиксные выражения оценивают (хотя без перехвата исключений, но все же, это что-то).

Мой код и полученный результат:

Postfix Tester:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class PostfixTester    
{
    /**
     * Reads and evaluates multiple postfix expressions.
     * @throws FileNotFoundException 
     */
    public static void main(String[] args) throws FileNotFoundException{
        String expression, again;
        int result;

        //Scanner in = new Scanner(System.in);
        Scanner in = new Scanner(new File("test.txt"));
        PostfixEvaluator evaluator = new PostfixEvaluator();
        while(in.hasNext()){
            expression = in.nextLine();
            System.out.println(expression);
            try{
                result = evaluator.evaluate(expression);
                System.out.println("The result is: " + result);
            }
            catch(EmptyCollectionException e){
                e.getMessage();
            }
            catch(InvalidPostfixExpressionException e){
                e.getMessage();
            }
            System.out.println();
        }
   }
}

Оценщик постфиксов:

import java.util.Stack;
import java.util.Scanner;


public class PostfixEvaluator
{
    private final static char ADD = '+';
    private final static char SUBTRACT = '-';
    private final static char MULTIPLY = '*';
    private final static char DIVIDE = '/';

    private ArrayStack<Integer> stack;

    /**
     * Sets up this evalutor by creating a new stack.
     */
    public PostfixEvaluator()
    {
        stack = new ArrayStack<Integer>();
    }

    /**
     * Evaluates the specified postfix expression. If an operand is
     * encountered, it is pushed onto the stack. If an operator is
     * encountered, two operands are popped, the operation is
     * evaluated, and the result is pushed onto the stack.
     * @param expr string representation of a postfix expression
     * @return value of the given expression
     */
    public int evaluate(String expr)
    {
        int op1, op2, result = 0;
        String token;
        Scanner parser = new Scanner(expr);

        while (parser.hasNext())
        {
            token = parser.next();

            if (isOperator(token))
            {
                op2 = (stack.pop()).intValue();
                op1 = (stack.pop()).intValue();
                result = evaluateSingleOperator(token.charAt(0), op1, op2);
                stack.push(new Integer(result));
            }
            else
                stack.push(new Integer(Integer.parseInt(token)));
        }
        if(stack.size() != 1){
            throw new InvalidPostfixExpressionException();
        }
        return result;
    }

    /**
     * Determines if the specified token is an operator.
     * @param token the token to be evaluated 
     * @return true if token is operator
     */
    private boolean isOperator(String token)
    {
        return ( token.equals("+") || token.equals("-") ||
                 token.equals("*") || token.equals("/") );
    }

    /**
     * Peforms integer evaluation on a single expression consisting of 
     * the specified operator and operands.
     * @param operation operation to be performed
     * @param op1 the first operand
     * @param op2 the second operand
     * @return value of the expression
     */
    private int evaluateSingleOperator(char operation, int op1, int op2)
    {
        int result = 0;

        switch (operation)
        {
            case ADD:
                result = op1 + op2;
                break;
            case SUBTRACT:
                result = op1 - op2;
                break;
            case MULTIPLY:
                result = op1 * op2;
                break;
            case DIVIDE:
                result = op1 / op2;
        }

        return result;
    }
}

Мой класс ArrayStack:

import java.util.Arrays;

public class ArrayStack<T> implements StackADT<T>
{
    private final static int DEFAULT_CAPACITY = 100;

    private int top;  
    private T[] stack;

    /**
     * Creates an empty stack using the default capacity.
     */
    public ArrayStack()
    {
        this(DEFAULT_CAPACITY);
    }

    /**
     * Creates an empty stack using the specified capacity.
     * @param initialCapacity the initial size of the array 
     */
    public ArrayStack(int initialCapacity)
    {
        top = 0;
        stack = (T[])(new Object[initialCapacity]);
    }

    /**
     * Adds the specified element to the top of this stack, expanding
     * the capacity of the array if necessary.
     * @param element generic element to be pushed onto stack
     */
    public void push(T element)
    {
        if (size() == stack.length) 
            expandCapacity();

        stack[top] = element;
        top++;
    }

    /**
     * Creates a new array to store the contents of this stack with
     * twice the capacity of the old one.
     */
    private void expandCapacity()
    {
        stack = Arrays.copyOf(stack, stack.length * 2);   
    }

    /**
     * Removes the element at the top of this stack and returns a
     * reference to it. 
     * @return element removed from top of stack
     * @throws EmptyCollectionException if stack is empty 
     */
    public T pop() throws EmptyCollectionException
    {
        if (isEmpty())
            throw new EmptyCollectionException("stack");

        top--;
        T result = stack[top];
        stack[top] = null; 

        return result;
    }

    /**
     * Returns a reference to the element at the top of this stack.
     * The element is not removed from the stack.  
     * @return element on top of stack
     * @throws EmptyCollectionException if stack is empty
     */
    public T peek() throws EmptyCollectionException
    {
        if (isEmpty())
            throw new EmptyCollectionException("stack");

        return stack[top-1];
    }

    /**
     * Returns true if this stack is empty and false otherwise. 
     * @return true if this stack is empty
     */
    public boolean isEmpty()
    {
        // To be completed as a Programming Project
        return top==0;
    }

    /**
     * Returns the number of elements in this stack.
     * @return the number of elements in the stack
     */
    public int size()
    {
        // To be completed as a Programming Project
        return top;
    }

    /**
     * Returns a string representation of this stack. 
     * @return a string representation of the stack
     */
    public String toString()
    {
        return stack.toString();
    }
}

Мой входной файл выражений (для целей тестирования последние два должны выдавать два исключения):

8 4 + 3 *
7 5 2 * +
3 1 + 4 2 - *
5 8 2 - +
5 8 - +
6 3 2 -

Мой фактический вывод:

8 4 + 3 *
The result is: 36

7 5 2 * +

3 1 + 4 2 - *

5 8 2 - +

5 8 - +

6 3 2 -

Очевидно, я ожидал, что первые четыре выражения последуют так же, как первое, а последние два - мои сообщения об исключениях, но я не могу понять, где я ошибся.

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Исключения генерируются, но поскольку класс PostfixTester использует e.getMessgage () , вы не увидите ошибки в выводе. Вы должны использовать System.out.println (e.getMessage ()) , чтобы напечатать сообщение. Но даже это изменение выведет null . Вам нужно перехватить исключения в методе PostfixEvaluator.evaluate () и снова выдать сообщение.

0 голосов
/ 30 августа 2018

Вы помещаете результат в стек оценки.

Вы повторно используете оценщик в тестере.

Оценщик не очищается при запуске второй итерации в тестере (результат предыдущего выражения находится в стеке).

Самый простой (и правильный) способ исправить это - изменить «вернуть результат»; "вернуть stack.pop ();"

В следующий раз воспользуйтесь отладчиком и переберите свой ошибочный код Это один из самых полезных навыков в программировании.

Утверждение предварительных условий тоже поможет. Убедитесь, что стек пуст, когда вы начинаете вычислять выражение.

...