Prosty Stos

D1
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

Witam, napisałem prosty stos, i niestety otrzymuje NullPointerException...
Co przeoczyłem, czego nie zainicjowałem:

Kopiuj
public class MojStos {
	Object tab[];
	int counter;
	
	
	public MojStos(int wielkosc){
		Object tab[] = new Object[wielkosc];
		counter = 0;
	}
	
	public void push(Object o)throws StosPrzepelnionyException{
		if(tab.length>counter){
			tab[counter++]=o;
		} else {
			throw new StosPrzepelnionyException();
		}
	}
	public Object pop() throws StosPustyException{
		if(counter<=0){
			throw new StosPustyException();
		} else {
			return tab[--counter];
		}
	}
	
	public void show(){
		/*for(Object item : tab){
			System.out.println(tab[item]);
		}*/
		System.out.println("===============");
		for(int i=0;i<=tab.length;i++){
			System.out.println(tab[i]);
		}
		System.out.println("===============");
		
	}
	
}

Klasa Main

Kopiuj
public class Main {
	
	public static void main(String[] args) {
		MojStos ms = new MojStos(3);
		
	
		try {
			ms.push(new Integer(8));
		} catch (StosPrzepelnionyException e) {
			e.printStackTrace();
			}
		}
	}
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
0

W konstruktorze nie inicjujesz pola.


D1
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

I tab i counter sa są przeciez zainicjowane?
tab = new Object(wielkosc);
counter = 0;

edytowany 1x, ostatnio: dombek100
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
0

Jak już wycinasz fragment, wycinaj z kontekstem:

Kopiuj
Object tab[] = new Object[wielkosc];
// ^^^^^^^^

;-)


edytowany 2x, ostatnio: Patryk27
lion137
  • Rejestracja:około 8 lat
  • Ostatnio:3 minuty
  • Postów:4888
0

Tu jest stos od autorow Algorytmow w Javie https://algs4.cs.princeton.edu/13stacks/Stack.java.html


A9
A9
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Zgorzelec/Görlitz
  • Postów:14
0

Cześć,
W konstruktorze tworzysz zupełnie nowy obiekt, który nic Ci nie daje później. Zamiast tego odwołaj się do zmiennych klasy:

Kopiuj
    public MojStos(int wielkosc){
        Spojler alert. Masz drugą zmienną i wymyśl co z pierwszą i zastanów się dlaczego tak jest:)
        this.counter = 0;
    }

i z tego co widzę jeszcze powinno Ci wywalić ArrayOutOfBoundException przy:

Kopiuj
        for(int i=0;i<=tab.length;i++){
            System.out.println(tab[i]);
        }

iterujesz o jeden obiekt za dużo. Sam zmień :)

Pozdrawiam,
adaszewski95

D1
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

W konstruktorze tworzysz zupełnie nowy obiekt, który nic Ci nie daje później. Zamiast tego odwołaj się do zmiennych klasy:

Kopiuj
    public MojStos(int wielkosc){
        Spojler alert. Masz drugą zmienną i wymyśl co z pierwszą i zastanów się dlaczego tak jest:)
        this.counter = 0;
    }

Hey, dzieki za odpowiedzi, dlaczego mówisz ze tworze obiekt który nic mi nie daje. Tworze Objekt Tab (tj. moj stos). To obiekt wiec muszę go zainicjować.

D1
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

i z tego co widzę jeszcze powinno Ci wywalić ArrayOutOfBoundException przy:

Kopiuj
        for(int i=0;i<=tab.length;i++){
            System.out.println(tab[i]);
        }

iterujesz o jeden obiekt za dużo. Sam zmień :)

jasna sprawa już poprawione:)

edytowany 2x, ostatnio: dombek100
A9
A9
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad 4 lata
  • Lokalizacja:Zgorzelec/Görlitz
  • Postów:14
1

Dobre rano :)

Już Ci tłumaczę, bo to jest kluczowe. Zauważ, że w klasie masz dwie **zdefiniowane **zmienne:

Kopiuj
    Object tab[];
    int counter;

Następnie tworzysz konstruktor, co jest jak najbardziej logiczne. Tylko w tym konstruktorze kluczowe jest to, żeby przypisać wartość zmiennym, które wcześniej zdefiniowałeś. Czyli tym powyżej. A to co robisz Ty w tym konstruktorze:

Kopiuj
    public MojStos(int wielkosc){
        Object tab[] = new Object[wielkosc];
        counter = 0;
    }

jest zdefiniowanie nowych zmiennych, które nie mają nic wspólnego z Twoimi zmiennymi klasy.
Zmienne, które zdefiniowałeś i przypisałeś im wartość w konstruktorze widzi tylko ten obiekt. Co to powoduje? Że do Twoich zmiennych klasy nie została przypisana żadna wartość a Ty próbujesz z nich skorzystać w dalszych metodach (myśląc, że przypisałeś im wartość, a tak na prawdę stworzyłeś nowe zmienne, które nie są widoczne poza konstruktorem) co skutkuje NullPointerem, ponieważ po stworzeniu obiektu nie zostały przypisane wartości zmiennym klasy. Dlatego też musisz koniecznie przypisać tym zmiennym wartość w konstruktorze. Tzn teraz patrzę to counterowi przypisujesz ale tworzysz tylko new Object tab = ...
Po prostu napisz tab = ... i będzie gitarrra :D
Mam nadzieję, że wytlumaczyłem zrozumiale.

Pozdrawiam,
adaszewski95

katelx
  • Rejestracja:prawie 10 lat
  • Ostatnio:4 miesiące
  • Lokalizacja:Hong Kong
1

pare uwag odnosnie twojego stosu ktore mozna latwo poprawic:

  • moglby byc type safe zamiast uzywac object
  • moglby nie rzucac wyjatkami
  • mogby nie miec ograniczen jesli chodzi o rozmiar
  • moglby nie miec wyciekow pamieci (przy pop)

np:

Kopiuj
import java.util.Optional;

public class Stack<TElement> {

    private Node<TElement> top;

    public void push(TElement element) {
        top = new Node<>(element, top);
    }

    public Optional<TElement> pop() {
        if (top == null) {
            return Optional.empty();
        }
        TElement popped = top.value;
        top = top.below;
        return Optional.of(popped);
    }

    public void show() {
        System.out.println("===============");
        Node current = top;
        while (current != null) {
            System.out.println(current.value);
            current = current.below;
        }
        System.out.println("===============");

    }

    private class Node<TElement> {
        final TElement value;
        final Node<TElement> below;

        Node(TElement value, Node<TElement> below) {
            this.value = value;
            this.below = below;
        }
    }


    public static void main(String[] args) throws Exception {
        Stack<String> stack = new Stack<>();
        stack.push("lol");
        stack.push("rotfl");
        stack.push("lmao");
        stack.show();
        stack.pop();
        stack.pop();
        stack.show();
        stack.pop();
        stack.pop();
    }
}
edytowany 1x, ostatnio: katelx
A9
adaszewski95
Myślę, że jak zaczyna swoją przygodę z javą to jeszcze nie wie co to Optional czy generics.
katelx
to dobra okazja zeby sie dowiedziec ;)
D1
nie wiem :), ale sie dowiem. Nardzo Wam dziękuje za pomoc. Cieszę się że znalazłem to forum.
FI
filemonczyk
czy to jest po bozemu ze element top ma referencje do elementu ponizej?
D1
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0
adaszewski95 napisał(a):

Dzięki za wskazówki. Zrobiłem poniższe:

Kopiuj
	public MojStos(int wielkosc){
		this.tab = new Object[wielkosc];
		this.counter = 0;
	}

Odwołuje się do konkretnych pól klasy które inicjuje w konstruktorze (błąd NullpointException rozwiązany :)

A9
adaszewski95
No i elegancko :) kolejnym krokiem jest wprowadzenie getterów i setterów, żebyś później mógł korzystać z tych zmiennych danego obiektu gdzieś indziej, np w main. Pozdrawiam :)
D1
Jeszcze raz dzięki!
Patryk27
@adaszewski95: wprowadzenie tutaj akcesorów doprowadziłoby do powstania leaking abstraction. Przecież równie dobrze można stos reprezentować listą jednokierunkową czy czymkolwiek innym.
A9
adaszewski95
@Patryk27: to prawda, ten przypadek nie jest do tego najlepszy. Raczej chodziło mi o późniejsze implementacje jakichś klas modelu. I w ogóle wygooglowałem "leaky abstraction", bo nie wiedziałem do końca co pod tym rozumieć, i pamiętam jak kiedyś była o tym mowa na teoretycznej informatyce :) ale znam to pod inną nazwą, tylko teraz nie wiem dokładnie pod jaką. Bym musiał odkopać książkę profesora z TI. Fajnie tak się udzielać na forum, zawsze można się czegoś ciekawego dowiedzieć :)
D1
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 6 lat
  • Postów:26
0

Co znaczy?

  • moglby nie miec wyciekow pamieci (przy push)
katelx
  • Rejestracja:prawie 10 lat
  • Ostatnio:4 miesiące
  • Lokalizacja:Hong Kong
2

mialam na mysli pop.
gdy bierzesz obiekty ze stosu to nie usuwasz ich z tablicy, tak wiec nawet jesli przestaniesz ich uzywac w innych miejscach, to referencja bedzie dalej trzymana i garbage collector ich nie usunie.
rozwiazaniem na ten problem (w twoim kodzie) byloby:

Kopiuj
counter--;
Object element = tab[counter];
tab[counter] = null;
return element;
edytowany 1x, ostatnio: katelx
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)