чтение стека Java из массива создает исключение ArrayIndexOutOfBoundsException - PullRequest
1 голос
/ 29 февраля 2012

Мне нужно заполнить стек из массива, затем распечатать элементы по порядку, а затем снова изменить порядок. У меня проблемы с тем, что я получаю ArrayIndexOutOfBoundsException и не могу понять, откуда он. Я попытался запустить отладку, и кажется, что я выталкиваю элементы, которые никогда не достигают последнего элемента. Ниже мой код:

public class arrayStack {

    private int top;
    private String[] storage;

    public arrayStack(int capacity)
    {
        storage = new String[capacity];
        top = -1;
    }

    public boolean isEmpty() {
        return (top == 0);
    }

    String peek() {
        return storage[top];    
    }

    String pop() {
        top--;
        return storage[top];
    }

    public void push(String str) {
        top++;
        storage[top] = str;
    }

}

StackMain.java:

public class StackMain {

    public static void main(String[] args) {
        //int j = 5;
        String[] list = new String[5];

        list[0] = "Beware";
        list[1] = "The";
        list[2] = "Ides";
        list[3] = "Of";
        list[4] = "March";

        arrayStack stack = new arrayStack(5);

        for(int i = 0; i < list.length; i++)
        {
            stack.push(list[i]);
        }

        for(int j = 0; j < list.length; j++)
            System.out.println(stack.pop());

    }

}

Ответы [ 8 ]

3 голосов
/ 29 февраля 2012

В pop() вам нужно вернуть элемент, который был вытолкнут, который является элементом с индексом старого значения top. Самый простой способ - изменить функцию на

String pop() {
    return storage[top--];
}

Редактировать
Вам также нужно изменить isEmpty() на return (top == -1). Вы также можете изменить реализацию, чтобы использовать size (количество элементов) вместо top (индекс самого высокого элемента), как уже упоминалось.

1 голос
/ 29 февраля 2012

Было бы замечательно, если бы вы могли включить универсальное средство java 1.5 для реализации стека. Тогда ваш стек будет более гибким. Он может содержать объекты любого типа (в вашем случае только Strings). Еще один совет - метод popВы должны указать сборщику мусора выбросить всплывающий объект следующим образом.(В случае, если вы используете непатентованные средства) Ниже приведена более гибкая реализация стека, упомянутая в эффективном выпуске java 2.

// Initial attempt to generify Stack = won’t compile!
public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = (E[])new E[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e) {
ensureCapacity();
elements[size++] = e;
}
public E pop() {
if (size==0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
1 голос
/ 29 февраля 2012

ваша функция pop () должна быть изменена.Вы должны сохранить хранилище [pop] во временной переменной, а затем уменьшить top на 1, а затем вернуть временную переменную

1 голос
/ 29 февраля 2012

Ваш поп-метод неверен. В вашем коде вершина начинается с отрицательного значения 1.

Когда вы нажимаете элемент, top становится 0. Когда вы открываете элемент, верхний становится -1, прежде чем вы получите доступ к элементу.

Кроме того, ваш пустой метод неверен. В начальном состоянии стека top = -1, и isEmpty проверяет, возвращает ли он 0. Изначально стек должен быть пустым.

1 голос
/ 29 февраля 2012

Пожалуйста, отметьте вопрос как домашнее задание.И что касается проблемы, проблема заключается в функции pop ().Вы сначала уменьшаете значение top, а затем возвращаете элемент.Но когда вы проверяете функцию push (), вы сначала увеличиваете, а затем добавляете элемент.Таким образом, если вы переместите top-- после получения элемента из стека, ваша проблема будет решена.

1 голос
/ 29 февраля 2012

Поскольку вы начинаете top с -1, после добавления 5 элементов из массива String top будет 4, что неверно, поскольку у вас есть 5 элементов.

Затем, когда вы пытаетесь выгрузить стек 5 раз, top возвращается к -1, а storage[-1] не существует, поэтому вы получаете ArrayIndexOutOfBoundsException

Start topв 0.

В качестве альтернативы, если вы уменьшите top после извлечения элемента из стека, вы не получите ошибку;но было бы лучше начать top с 0, потому что top действительно представляет количество элементов в вашем стеке.

1 голос
/ 29 февраля 2012

Если вы push(String) всего один элемент, с вершиной, инициализированной -1, каким будет значение вершины после нажатия?

Теперь посмотрите на вашу pop() функцию, она уменьшает top до попытки получить запрошенный элемент, так к какому индексу массива он будет пытаться получить доступ, если вы нажали только один элемент?

1 голос
/ 29 февраля 2012

В вашем конструкторе для arrayStack вы должны установить top на 0, а не на -1. В вашем методе isEmpty вы даже проверяете, что top == 0, поэтому ясно, что top == 0 означает пустой, а не top == -1. Вот почему вы всегда пропускаете последний элемент, когда извлекаете значения из стека; установка первого элемента с шагом top в 0.

О, и я пропустил то, что сказал Том ниже: уменьшив значение top до того, как вы найдете значение в верхней части, вернет неправильный элемент. Его код ниже предпочтительнее, но для начинающего это может быть проще для понимания:

public String pop() {
    String topValue = storage[top];
    top--;
    return topValue;
}
...