Problem mit einfach Verketter Liste



  • Hallo,

    ich habe eine kurze Frage:

    Ich möchte einen FIFO-Speicher mit Hilfe einer verketten Liste realisieren
    an den man beliebig viele Elemente anfügen kann.

    Dabei soll es drei Operationen geben:

    push : ein Element am Listenanfang anfügen.
    pop: soll einen Zeier auf das letzte element zurückgeben und dieses dann aus der
    Liste entfernen.
    allesausgeben: soll den gesamten Speicherinhalt ausgeben

    Die Funktionen push und allesausgeben funktionieren schon so weit.

    Das Problem liegt nun bei der Funktion pop.
    Das Entfernen des letzten Elements am Listenende funktioniert schon.
    Die funktion liefert auch einen Zeiger auf das letzte Element zurück,
    Mit ->wert lasse ich dann in der main() den Wert des Wlements ausgeben.
    Der Wert wird auch wie geünscht ausgegeben, jedoch auch alle anderen Listenwerte, was ja nicht gewünscht ist, es soll ja nur der Wert des letzten Listenelements zurückgegeben werden.

    Wo liegt der Fehler 😞 😞 😞

    So hier mal der code:

    # include <stdio.h>
    # include <stdlib.h>
    
    struct element {
    	int wert;
    	struct element*next;}*start=NULL;
    
    void push(wert){                           //push Element
    
    struct element *neu;
    	neu= (struct element*) malloc(sizeof(struct element));
    
    //Falls Liste leer
    if (start==NULL){
    start=neu;
    neu->next=NULL;
    neu->wert=wert;
    }
    else{
    neu->next=start;
    start=neu;
    neu->wert=wert;
    
    }
    }
    
    struct element *pop(void){                       //pop elemnt
    
    struct element *speicher, *speicher2;
    speicher=start;
    speicher2=speicher;
    while(speicher!=NULL){
    
    		printf("%d\n",speicher->wert);
    		if (speicher->next==0)
    			break;
    		speicher2=speicher;
    		speicher=speicher->next;		
    }
    
    speicher2->next=NULL;
    
    return speicher;
    }
    
    int allesausgeben(void){
    struct element *speicher=start;
    	while(speicher!=NULL){
    		printf("%d\n",speicher->wert);
    		speicher=speicher->next;	
    	}
    }
    
    int main(void){
    int zahl=0;
    push(9);              // 9 an Pufferanfang einfügen
    push(3);              // 3 an Pufferanfang einfügen
    push(4);
    					  // 4 an Pufferanfang einfügen
    allesausgeben();
    zahl=((pop())->wert);
    printf("%d\n",zahl);
    allesausgeben();
    system("PAUSE");
    
    	return 0;
    
    }
    

    Die Ausgabe erfolgt dann zu:

    4
    3
    9
    4 //Diese zeichen sollt nicht mit ausgegeben werden, verursacht von pop()
    3 //Diese zeichen sollt nicht mit ausgegeben werden, verursacht von pop()
    9 //Diese zeichen sollt nicht mit ausgegeben werden, verursacht von pop()
    9 // nur die 9 sollt pop() ausgeben
    4
    3

    Die Ausgabe sollte eigentlich so aussehen:
    4 // allesausgeben()
    3 // allesausgeben()
    9 // allesausgeben()
    9 // pop()
    4 // allesausgeben() nach pop
    3 // allesausgeben() nach pop

    Wäre Dankbar für Tipps......



  • Dann mach doch das printf in Zeile 41 weg. 🙄

    Du musst an deinem Einrückungsstil arbeiten.

    Danke das du die Code-Tags benutzt hast. Nimm aber ruhig den C-Button. Dann wird es farbig und bint.



  • malloc99 schrieb:

    Wo liegt der Fehler 😞 😞 😞

    pop() ist Quark.
    Mal Dir Deine queue auf ein Blatt und denk nochmal drüber nach.
    Denk auch an den Sonderfall, dass nur ein Element in der Liste ist.

    Eigentlich darst Du pop() auch nur aufrufen, wenn start!=NULL.

    Aktivier auch die Warnungen in Deinem Compiler/ Deiner IDE: push() s Parameter hat keinen Typ(Z.12), allesausgeben() hat einen Rückgabewert int , gibt aber nix zurück(Z.55/61).

    Alles kleines Hilfsmittel: bau asserts ein:

    #include <assert.h>
    
    void allesausgeben(void){
      assert(start!=NULL);
      struct element *speicher=start;
        while(speicher!=NULL){
          printf("%d\n",speicher->wert);
          speicher=speicher->next;   
        }
    
    void f(){
      if(start) // guter Stil.
        allesausgeben();
    }}
    


  • Ok,

    Danke für die schnelle Hilfe, werd den Code noch mal überarbeiten.

    Bei " Pop" eines Elements hab ich auch noch free() vergessen, muss auch noch rein.



  • So mal ein Update,

    den Sonderfall dass nur 1 Element vorhanden verarbeitet pop nun auch.
    Ist kein Element vorhanden, wird das programm mit assert fehlercode beendet.

    Noch eine frage zum Speicher freigeben:

    ich gebe mit pop ja einen Zeiger auf das letzte listenelement zurück, nach der Konsolenausgabe gebe ich den Speicherbereich dann wieder mit free frei.

    Gibt es eine Möglichkeit die Speicherfreigabe mit in die Funktion pop () einzubauen?

    Hier noch mal ein Codeupdate:

    # include <stdio.h>
    # include <stdlib.h>
    # include <assert.h>
    
    struct element {
    	int wert;
    	struct element*next;
         }*start=NULL;
    
    void push(wert){                               //push Element
    	struct element *neu;
    	neu= (struct element*) malloc(sizeof(struct element));
    
    	if (start==NULL){
    		start=neu;
    		neu->next=NULL;
    		neu->wert=wert;
    	}
    
    	else{
    		neu->next=start;
    		start=neu;
    		neu->wert=wert;
    	}
    
    }
    
    struct element *pop(void){                    //pop elemnt
    	struct element *speicher, *speicher2;
    	assert(start!=NULL);
    	speicher=start;
    	speicher2=speicher;
    
    	if(speicher->next==NULL){                // Sonderfall es gibt nur ein Listenelement
    		start=NULL;
    		return speicher;  
    	}
    
    	while(speicher!=NULL){
    		if (speicher->next==0)
    			break;
    		speicher2=speicher;
    		speicher=speicher->next;		
        }
    		speicher2->next=NULL;
    		return speicher;
    }
    
    void allesausgeben(void){
    	struct element *speicher=start;
    	assert(start!=NULL);
    
    	while(speicher!=NULL){
    		printf("%d\n",speicher->wert);
    		speicher=speicher->next;	
    	}
    }
    
    void ausgabe(void){
    	if(start)
    		allesausgeben();
    }
    
    int main(void){
    int zahl=0;
    struct element *last;
    
    //push(9);						 // 9 an Pufferanfang einfügen
    //push(3);						 // 3 an Pufferanfang einfügen
    //push(4);					     // 4 an Pufferanfang einfügen
    
    ausgabe();                       // Erste ausgabe der 3 Elemente
    
    last=pop();                    // Ausgabe/Löschen des letzten Listenelements
    printf("%d\n",last->wert);         
    free(last);                     // Speicher des oben gelöschten Elements freigeben
    
    ausgabe();
    
    system("PAUSE");
    return 0;
    
    }
    

    Gruß

    malloc99



  • malloc 99 schrieb:

    ich gebe mit pop ja einen Zeiger auf das letzte listenelement zurück, nach der Konsolenausgabe gebe ich den Speicherbereich dann wieder mit free frei.

    Gibt es eine Möglichkeit die Speicherfreigabe mit in die Funktion pop () einzubauen?

    Ja.
    Wenn Du int in die Liste steckst, solltest Du auch nur int rausbekommen. Sonst ist das ganze ja eine Art "Factory" für Listenelemente. 😉
    Oder ist das Teil der Aufgabenstellung?

    malloc 99 schrieb:

    struct element *pop(void){                    //pop elemnt
    	struct element *speicher, *speicher2;
    	assert(start!=NULL);
    	speicher=start;
    	speicher2=speicher;
    
    	if(speicher->next==NULL){                // Sonderfall es gibt nur ein Listenelement
    		start=NULL;
    		return speicher;  
    	}
    
    	while(speicher!=NULL){
    		if (speicher->next==0)
    			break;
    		speicher2=speicher;
    		speicher=speicher->next;		
        }
    		speicher2->next=NULL;
    		return speicher;
    }
    

    Das scheint mir immer noch komplizierter als nötig.
    Ich wette, Du kannst das auf die Hälfte der Zeilen eindampfen, wenn Du Dich wirklich nochmal anstrengst!

    Los komm: Mein Bildschirm ist zu klein für sowas! 🙂



  • Warte immer noch auf die Erleuchtung......

    wenigstes ein return weniger..... 😞 😞 😞

    popupdate:

    struct element *pop(void){                    //pop element
    	struct element *speicher=start, *speicher2=start;
    	assert(start!=NULL);
    	speicher2->next=NULL;
    	if(speicher2->next==NULL)
    		start=NULL;
    	while(speicher!=NULL){
    		if(speicher->next!=NULL){               
    			speicher2=speicher;
    			speicher=speicher->next;
    	   	}
    		else
    			break;
         }
    	speicher2->next=NULL;
    	return speicher;
    }
    

    Gruß

    malloc99



  • malloc 99 schrieb:

    Warte immer noch auf die Erleuchtung......

    wenigstes ein return weniger..... 😞 😞 😞

    popupdate:

    struct element *pop(void){                    //pop element
    	struct element *speicher=start, *speicher2=start;
    	assert(start!=NULL);
    	speicher2->next=NULL;
    	if(speicher2->next==NULL)
    		start=NULL;
    	while(speicher!=NULL){
    		if(speicher->next!=NULL){               
    			speicher2=speicher;
    			speicher=speicher->next;
    	   	}
    		else
    			break;
         }
    	speicher2->next=NULL;
    	return speicher;
    }
    

    Naja, wahrscheinlich habe ich das Maul zu voll genommmen, was das Verkürzen anbelangt. 🙄

    Aber den Vorschlag, pop() zu ändern in

    int pop(){
      // ....
      int i = xyz->next->wert;
      free(xyz->next);
      xyz->next=NULL;
      return i;
    }
    

    Hast du mitbekommen?



  • Ja hab ich mitbekommen,

    stimmt ja die rückgabe des int wertes reicht in diesem Fall ja.

    Hätte man eine struct mit mehr elementen, die man zurückgeben will,

    zb. wert, name , datum.....

    kann man das free dann aber nicht in pop() reinziehen.

    Deshalb habs ich mal rausgelassen

    Vielen Dank für die gute Unterstützung , einfach klasse..

    Gruß

    malloc 99



  • Globale Variablen sind Schrott.


Anmelden zum Antworten