Java Buch-Liste --> Fehler beim Einfügen

raffiSSL

Lt. Junior Grade
Registriert
Feb. 2006
Beiträge
289
Hallo, ich habe eine Buchliste geschrieben, als doppelt verkettete Liste. Ein Buch hat nur Titel und Preis als Attribute.
Das Ausführen des Programms klappt soweit, aber sobald ich die Daten eines Buchs eingegeben habe kommt eine Fehlermeldung, die mir sagt das irgendetwas ins leere zeigt.
Dabei überprüfe ich doch beim Einfügen ob der head = null ist, oder liegt es garnicht daran?

Code:
Exception in thread "main" java.lang.NullPointerException
	at Liste.einfuegen(Liste.java:19)
	at Main.go(Main.java:28)
	at Main.main(Main.java:47)

Und hier nun die Codes dazu(ich poste mal jeweils nur die wichtigen Zeilen bzw. Methoden):

Main.java
Code:
public void go () {
		in = new SimpleInput();
		data = new Buch();
		eintrag = new Liste();
		int i;
		char r;
		System.out.println("Bücherverwaltung");
		System.out.println("==================");
		System.out.println("Menü:");
		System.out.println("Buch hinzufügen --> 1");
		System.out.println("Buch löschen --> 2");
		System.out.println("Bücher anzeigen --> 3");
		
		r = 'j';
		
		while (r == 'j') {
			i = in.readInt("Auswahl: ");
			if (i == 1) {
				data.readData();
				head = new Knoten(data);
				eintrag.einfuegen(head,data);
			}
...
public static void main (String args[]) {
		Main r = new Main();
		r.go();
	}

Liste.java
Code:
public void einfuegen (Knoten head,Buch b) {
    	Knoten temp = new Knoten(b);
    	if (head == null) {
    		head = temp;
    		head.setNext(null);
    		head.setPrev(null);
    	}
        if (head.getNext().getData().getTitel().compareTo(b.getTitel()) == 0) {
            temp.setPrev(head.getPrev());
            head.setPrev(temp);
            temp.setNext(head);
            temp.getPrev().setNext(temp);
        }
        else {
            einfuegen(head.getNext(),b);
        }
    }

Danke für die Hilfe und Mahlzeit :cool_alt:
 
Mit den Code-Schnipseln kann der Head gar nicht NULL werden:

Code:
head = new Knoten(data);
eintrag.einfuegen(head,data);

Ich weiß ja nicht, wie KNOTEN im Konstruktor initialisiert wird, aber ich gehe mal davon aus, dass die Neben-Knoten "prev" und "next" nicht initialisiert werden, also NULL sind.

Wenn dann:

Code:
head.getNext().*

aufgerufen wird, gibt es die o.a. NullPointerException!
 
Hallo rafiSSL,

mal allein auf die Einfügen-Methode bezogen.

Sollte der head tatsächlich mal mit NULL übergeben werden, legst Du Dir das Ei auch mit Deinem Abfangversuch.

Du setzt den neuen temp-Knoten als Head und setzt den nachfolger, sowie Vorgänger auf "NULL".

if (head == null) {
head = temp;
head.setNext(null);
head.setPrev(null);
}


Direkt im Anschluss wendest die getData-Methode auf den Nachfolger an, den Du gerade NULL gesetzt hast.

if (head.getNext().getData()....

an der Stelle crasht es

VG
 
Hallo, habe das Problem mit dem Einfügen unter Kontrolle bekommen.
Sieht jetzt so aus:
Code:
public void einfuegen (Knoten head,Buch b) {
    	Knoten temp = new Knoten(b);
    	
    	if (head == null) {
    		head = temp;
    		head.setNext(null);
    	}
    	
    	if (head.getData().getTitel().compareTo(b.getTitel()) == 1) {
    		temp.setNext(head);
    		head.setPrev(temp);
    		head = temp;
    	}
    	else if (head.getNext() == null) {
    		head.setNext(head);
    		temp.setPrev(head);
    		temp.setData(b);
    	}
        else {
            einfuegen(head.getNext(),b);
        }
    }

Wenn da noch ein Fehler sein sollte bitte sagen ;D
Allerdings scheitert es jetzt an der Ausgabe. Er springt bei folgender Methode immerwieder in die Rekursion wenn ich 1 oder mehr Bücher anlege, bei 0 Büchern gibt er den Text aus, das klappt also.
Ich sehe den Fehler beim besten Willen nicht. :(
Code:
    public void durchlaufvor (Knoten head) {
    	if (head == null) {
    		System.out.println("Keine Bücher in der Liste vorhanden.");
    		return;
    	}
    	
    	if (head.getNext() == null) {
    		head.getData().ausgabe();
    	}
        else {
            head.getData().ausgabe();
            durchlaufvor(head.getNext());
        }
    }

Ich danke schonmal, und falls ihr noch andere Klassen-Daten bzw. Methoden oder Infos benötigt dann sagt bescheid.

mfg :)
 
Machs doch einfach so:
PHP:
public void durchlaufvor (Knoten head) {
   if(head == null) {
      System.out.println("Keine Bücher in der Liste vorhanden.");
   } else {
      do{
         head.getData().ausgabe();
         head = head.getNext();
      } while(head != null);
   }
}
 
Danke, hätte ich auch selber drauf kommen können das mal ohne rekursion zu testen. ABER: Jetzt spielt das programm total verrückt, sobald ich nach dem erstellen eines Buches die Liste anzeigen will läuft das programm...und läuft...und läuft...also gibt das Buch aus mehrere male aus. Und beim Schließen der Konsole startet selbige wieder neu und macht fein weiter mit dem ausgeben des Buches. Nur das Schließen von Eclipse beendet das Ganze. Es kommt jedoch kein StackOverFlow Fehler.

mfg

EDIT: Sobald ich die Rekursion als Kommentar setze funktioniert die Ausgabe, jedoch nur für das zu letzt eingetragene Buch, wenn das helfen sollte.
 
Zuletzt bearbeitet:
Könnte es sein, dass das letzte Buch in der Liste irgendwie nicht auf null verweist sondern wieder auf sich selbst? Oder dass die getNext()-Funktion nicht das tut was sie sollte?
Wenn du Eclipse nutzt könntest du auch mal den Debugger anwerfen und dir genau ansehen (man kann jeden Programmschritte einzeln "steppen" und sich gleichzeitig die Daten anschauen) was so passiert...

Edit:
Das
Code:
head.setNext(head);
sieht für mich SEHR verdächtig aus...

Edit2:
Mal ganz unverbindlich und ohne Test des Codes würde ich so eine Einfügefunktion bauen:
PHP:
public Knoten einfuegen (Knoten head,Buch b) {
	Knoten temp = new Knoten(b);
	if(head == null){      // Liste leer
		head = temp;
		head.setNext(null);
	} else {
		// Position suchen	
		Knoten current = head;
		while(current != null && current.getData().getTitel().compareTo(b.getTitel()) < 0){
			current = current.getNext();
		}
		
		if(current == head){	// an erster Position einfügen
			temp.setNext(head);
			head.setPrev(temp);
			head = temp;
		} else {		// an späterer Position einfügen
			// voriges Element wird benötigt weil die Schleife oben immer "zu weit geht"
			Knoten prev = current.getPrevious();     
			prev.setNext(temp);
			temp.setPrevious(prev);
			if(current != null){	// einfügen in der Mitte => nachfolgendes Element muss auch angepasst werden
				current.setPrevious(temp);
				temp.setNext(current);
			}			
		}
	}
	return head;	//damit man den head auch updaten kann im Hauptprogramm! Das passiert bei dir nämlich nicht und damit bringt die Sortierung auch wenig weil man irgendwo in der Mitte anfängt!
}
 
Zuletzt bearbeitet:
OK. Das war es erstmal, zumindest für den StackOverFlow. Danke. Läuft zwar immernoch nicht richtig, aber der Fehler ist erstmal behoben.

:)
Ergänzung ()

Ich habe deinen Quelltext mal durchgeschaut und auch gut verstanden. Nur tue ich mich etwas schwer mit dem Ereignis, wenn schon ein head besteht und und vor diesem eingefügt werden muss.
Du hast es mit (current == head) gelöst, ich habe mir es folgendermaßen gedacht, nur leider kommt bei der Ausgabe wieder nur das letzte Buch.
Code:
    	if (head == null) {
    		head = temp;
    		tail = temp;
    		head.setNext(null);
    		head.setPrev(null);
    	}
    	else {
    		while (head != null && head.getData().getTitel().compareTo(b.getTitel()) < 0) {
    			head = head.getNext();
    		}
    		if (head.getData().getTitel().compareTo(b.getTitel()) == 1 && head.getPrev() == null) { // soll eigentlich (current == head) enstprechen!?
    			temp.setNext(head);
    			head.setPrev(temp);
                        head.setNext(null);
    			head = temp;
    		}
    		else if (head.getData().getTitel().compareTo(b.getTitel()) == 1) { // einfuegen zwischendrin
    			temp.setPrev(head.getPrev());
    			head.getPrev().setNext(temp);
    			temp.setNext(head);
    			head.setPrev(temp);
    		}
               else {
    			head.setNext(temp);
    			temp.setPrev(head);
    			tail = temp;
    			temp.setNext(null);
    		}
    	}

Müsste doch auch so klappen oder nicht?

mfg

EDIT: Bin jetzt schon soweit, das er zumindest 2 Bücher ausgibt, wenn ich auch 2 Bücher eingefügt habe, nur leider gibt er mit das zu letzt eingefügte Buch 2 mal aus.
 
Zuletzt bearbeitet:
Lass dir doch bei der Ausgabe mal immer anzeigen, auf was next und previous jeweils stehen.
 
Zurück
Oben