Problem mit sequienziell gespeicherter Zeiger-Liste



  • Hallo Community,

    in meinem Studiengang haben wir vor einiger Zeit das Thema "sequienziell gespeicherte Listen" behandelt. Hierfür haben wir eine Übungsaufgabe von unserem Professor erhalten. Eigentlich seh ich mich recht Fit bei diesem Thema, aber irgendwie mag ich meinen Fehler nicht so recht finden.

    Vorbemerkung: Es handelt sich hierbei um eine Zeiger-Liste:

    typedef struct {
        int maxSize;
        int size;
        Element *daten[100];
    } ZList;
    

    die mit Elementen des Types

    typedef struct Element{
           int id;
           double value;
           struct Element *next; //nur für anderen Aufgabentyp relevant, hier nicht
    }Element;
    

    Die Aufgabe lautet:

    Mit

    addZElement(ZList *list,Element *newElement)

    zu dieser Liste (bereits mit 5 Elementen gefüllt) ein Element mit der ID 12 und dem Wert 18.5 hinzuzufügen.

    Hier mein Code (Funktionen wie createElement und createZList funktionieren fehlerfrei (sind vom Prof. so beigefügt) und sind in einer Headerdatei):

    #include "Header.h" 
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void printZList (ZList *list){
    	int i=0;
    	Element *hElement;
    	printf("Sequentiell gespeicherte Zeiger-Liste\n");
    	for(i=0; i<list->size;i++){
    		hElement=list->daten[i];
    		printf("ID = %i, Value = %3.2f\n", hElement->id,  hElement->value);
    	}
    	printf("\n\n");
    }
    
    int addZElement(ZList *list, Element *newElement){
    
    	if(list->size==list->maxSize) return 0;
    	list->daten[list->size+1]=newElement;
    	list->size++;
    
    	return list->size;
    
    int main (void){
    
      	ZList *ZList1=createZList();
    
     	//Element zum Hinzufügen mit ID 12 und Wert 18.5
            Element *putElement = createElement(12,18.5);
    
    	//Anzeigen aller Listen
    	printZList(ZList1);
    
    	//Hinzufügen Element zur jeder Liste
    	addZElement(ZList1, putElement);
    
    	//Anzeigen Liste nach hinzufügen
    	printZList(ZList1);
    
    }
    

    Das Element putElement wurde richtig erzeugt (wurde geprüft mit printf() mit den jeweiligen werden). Der Fehler ereignet sich beim zweiten Aufrufen der printZList Funktion nach dem Hinzufügen in Zeile 12. Hier schmiert das Programm ab.

    Danke schonmal für eure Hilfe!



  • Die addZElement-Funktion ist fehlerhaft.
    Überlege dir noch mal die Indizes deiner Liste (in C sind Arrays immer nullbasiert, d.h. der Index geht von 0 bis n-1).


  • Mod

    Zeig createElement und createZList! Benutze Copy&Paste für Code. Der gezeigte Code kann nicht dein Originalcode sein, da stimmt ja nicht einmal die Klammersetzung! Siehe:
    http://www.c-plusplus.net/forum/304133

    Dir ist schon klar, dass ein Zeiger und das worauf er zeigt zwei ganz unterschiedliche Sache sind? Deine List speichert im Moment nur Zeiger auf Dinge. Diese Dinge müssen auch irgendwo existieren. Im Moment hätte ich den Verdacht, dass du zwar in createElement ein Element erstellst, aber sofort wieder verwirfst. Der Zeiger auf dieses verworfene Elemente führt noch eine Weile ein untotes Dasein (Zugriff auf ungültige Speicherbereiche darf auch gut gehen, das Verhalten ist undefiniert), daher funktioniert deine erste Ausgabe noch. Aber spätestens nachdem ein paar andere Funktionen über den fraglichen Speicherbereich geschrieben haben, stürzt das Programm ab.

    Die ganze Aufgabe kommt mir nicht sehr sinnvoll vor. Bist du sicher, dass du das Thema richtig verstanden hast? Sollen die Daten nun sequenziell gespeichert werden oder als verkettete Liste? Falls ersteres: Wieso dann der next-Zeiger in Element und wieso ist ZList::daten ein Feld von Zeigern? Falls letzteres: Wieso wird dann der next-Zeiger nicht benutzt und wieso ist ZList::daten ein Feld?



  • Danke dir, Th69. So ein dummer Fehler aber auch. Jetzt funktioniert alles. Bekomme auch die Ergebnisse heraus die es sein sollen.

    Zu dir SeppJ:

    Ja, die eine kleine habe ich beim Kopieren nicht mitkopiert. Habe den Code um einiges gekürzt.

    Es ist auch noch eine verkettete Liste drin gewesen, deswegen der next Zeiger.
    Außerdem hab es auch noch eine sequenziell gespeicherte Liste, die eben nicht die Zeiger, sondern die tatsächlichen Elemente enthielt. Die Übung diente lediglich dazu, den Unterschied zwischen diesen Listen zu verdeutlichen.

    Die Aufgabenstellung beinhaltet, jede Liste zunächst auszugeben, den Durchschnittswert der Elemente zu berechnen und anschließend ein weiteres Element hinzuzufügen und das ganze nochmal zu machen.

    An sich war die Aufgabe sehr einfach, wie ich empfinde. Hatte das ganze auch in 20 Minuten runtergeschrieben.

    Zu deiner Befürchtung mit dem Element, dass ich eventuell verwerfe. In der createElement wird hierfür Speicherplatz reserviert und anschließend mit Beispielwerten gefüllt. Somit exestieren diese doch auch dort?!

    Und ich habe schon verstanden, dass meine Liste nur Zeiger auf Elemente beinhaltet.

    Trotzdem Danke für die schnelle Antwort.

    Falls noch Interesse Interesse an den Funktionen besteht, stell hier mal den Header Code rein:

    #ifndef __LISTDEFS_H
    #define __LISTDEFS_H
    
    #include <stdio.h>
    #include <stdlib.h>
    
    // Strukturdefinitionen fuer die unterschiedlichen Listen
    typedef struct Element{
           int id;
           double value;
           struct Element *next;
    }Element;
    
    typedef struct {
        int maxSize;
        int size;
        Element daten[100];
    } SList;
    
    typedef struct {
        int maxSize;
        int size;
        Element *daten[100];
    } ZList;
    
    typedef struct{
        Element *start;
        Element *ende;
    } VList;
    
    // Hilfsfunktionen zur Elementerzeugung und Listenaufbau
    
    // Ein Element erzeugen
    Element *createElement(int id, double val){
    	Element *e = (Element *) malloc (sizeof (Element));
    	e->id = id;
    	e->value = val;
    	return e;
    }
    
    //Sequenziell gespeicherte Liste
    SList *createSList(){
    	SList *sList = (SList *) malloc (sizeof(SList));
    	Element *e;
    	sList->maxSize = 100;
    	e = createElement(0,25);
    	sList->daten[0] = *e;
    	free( e);
    	e = createElement(1,55);
    	sList->daten[1] = *e;
    	free(e);
    	e= createElement(2,75);
    	sList->daten[2] = *e;
    	free(e);
    	e= createElement(3,115);  
    	sList->daten[3] = *e;
    	free(e);
    	sList->size = 4;
    	return sList;
    }
    
    ZList *createZList(){
    	ZList *zList = (ZList *) malloc (sizeof(ZList));
    	zList->size = 5;
    	zList->maxSize = 100;
    	zList->daten[0] = createElement(0,15);
    	zList->daten[1] = createElement(1,25);
    	zList->daten[2] = createElement(2,35);
    	zList->daten[3] = createElement(3,45); 
    	zList->daten[4] = createElement(4,55); 
    	return zList;
    }
    VList *createVList(){
    	// Liste initialisieren
    	VList *l = (VList *) malloc (sizeof(VList));
    	Element *p[4];
    	l->start = createElement(0,0);
    	l->ende = createElement(0,0);
    	// Einige Werte eintragen
    	p[0] = createElement(1,17);
    	p[1] = createElement(2,35);
    	p[2] = createElement(3,36);
    	p[3] = createElement(4,20);
    
    	// manueller Listenaufbau!!
    	l->start->next=p[0];
    	p[0]->next = p[1];
    	p[1]->next = p[2];
    	p[2]->next = p[3];
    	p[3]->next = l->ende;
    	l->ende->next = NULL;
    
    	return l;
    }
    
    #endif;
    

Anmelden zum Antworten