Iteratoren - Stack als Klassentemplate - die zweite



  • Hy!
    Und schon wieder ich ­čÖä
    Ich habe hier einen Stack in Form eines Klassentemplates geschrieben.

    // Stack.h //
    
    #ifndef STACK_H_
    #define STACK_H_
    
    class StackError {			// Exceptionklasse
    public:
    	char *what(void);
    	StackError(char *);
    private:
    	char *error;
    };
    
    StackError::StackError(char *error) {
    	this->error = error;
    }
    
    char *StackError::what(void) {
    	return error;
    }
    
    template<class ANY_TYPE>
    class Stack {
    public:
    	Stack(void);
    	~Stack(void);
    	void push(const ANY_TYPE &) throw (StackError);
    	void top(ANY_TYPE &) throw (StackError);
    	void pop(void) throw (StackError);
    	bool is_empty(void);
    private:
    	struct list_el {
    		ANY_TYPE data;
    		list_el *pnext;
    	};
    	list_el *stack_pointer;
    };
    
    template <class ANY_TYPE>
    Stack<ANY_TYPE>::Stack(void) {
    	stack_pointer = NULL;
    }
    
    template <class ANY_TYPE>
    void Stack<ANY_TYPE>::push(const ANY_TYPE &element) throw (StackError) {	// schiebt Element in den Stack
    	list_el *temp = new list_el;	// erstellt neues Listenelement
    	if(temp == NULL)					// wenn kein Speicher vorhanden ...
    		throw StackError("kein Heapspeicher frei!");
    	temp->data = element;			// speichert uebergebene Daten
    	temp->pnext = stack_pointer;	// Verkettung
    	stack_pointer = temp;			// StackPointer auf neues Element
    }
    
    template <class ANY_TYPE>
    void Stack<ANY_TYPE>::top(ANY_TYPE &element) throw (StackError) {	// liest erstes Element
    	if(is_empty())
    		throw StackError("Stack ist leer!");
    	element = stack_pointer->data;	// gibt erstes Element zurueck
    }
    
    template <class ANY_TYPE>
    void Stack<ANY_TYPE>::pop(void) throw (StackError) {				// loescht erstes Element
    	if(is_empty())
    		throw StackError("Stack ist leer!");
    	list_el *temp = stack_pointer;
    	stack_pointer = stack_pointer->pnext;
    	delete temp;
    }
    
    template <class ANY_TYPE>
    bool Stack<ANY_TYPE>::is_empty(void) {
    	if(stack_pointer == NULL)	// prueft ob erstes Element vorhanden
    		return true;
    	else
    		return false;
    }
    
    template <class ANY_TYPE>
    Stack<ANY_TYPE>::~Stack(void) {
    	delete stack_pointer;
    }
    
    #endif // STACK_H_
    

    Habe das ganze noch mit Exceptions gemacht zur Fehlerbehandlung, dass jetzt auch funktionieren d├╝rfte. Nun soll ich noch einen Iterator der um ein oder mehrere Elemente weiter geschaltet werden kann (++ bzw. +=) schreiben, die Iteratorfunktionen begin() und end() und dann noch insert und erase zum Einf├╝gen von Elementen, oder eben halt wieder zum l├Âschen.
    Ich bin jetzt schon die ganze zeit da am rumprobieren, aber irgendwie werd ich mit den Iteratoren einfach nicht fertig. Jeder Versuch endet in der M├╝lltonne, weil ich den Code anscheiend immer so verschandel, dass der Compiler nur noch M├╝ll ausspuckt. Habe auch schon nach den FAQs hier geschaut und meinen Nachbar google. Leider liegt mein Buch zu Hause und ich bin grad unerwegs, und finde auch keine Quelle die es f├╝r mich klar ersichtlich macht. Ich glaube ich habe mich schon wieder selber verwirrt und blick jetzt mal wieder garnicht durch ­čśĽ

    Achja, hier noch die main.ccp

    // main.cpp //
    
    #include <iostream>
    #include "Stack.h"
    using namespace std;
    
    int main(void) {
    	float zahl_float;
    
    	Stack<float> *float_stack = new Stack<float>();
    	cout << "float_stack erzeugt" << endl;
    
    	try {
    		if(float_stack->is_empty())
    			cout << "is_empty()=true" << endl;
    		else
    			cout << "is empty()=false" << endl;
    		float_stack->push(3.1415);
    		cout << ">>3.1415" << endl;
    		float_stack->push(2.322);
    		cout << ">>2.322" << endl;
    		float_stack->push(1.333);
    		cout << ">>1.333" << endl;
    		float_stack->top(zahl_float);
    		cout << zahl_float << "<<" << endl;
    		float_stack->pop();
    		float_stack->top(zahl_float);
    		cout << zahl_float << "<<" << endl;
    		if(float_stack->is_empty())
    			cout << "is_empty()=true" << endl;
    		else
    			cout << "is empty()=false" << endl;
    		float_stack->pop();
    		float_stack->top(zahl_float);
    		cout << zahl_float << "<<" << endl;
    		float_stack->pop();
    		if(float_stack->is_empty())
    			cout << "is_empty()=true" << endl;
    		else
    			cout << "is empty()=false" << endl;
    	}
    	catch(StackError err) {
    		cout << err.what() << endl;
    	}
    	return 0;
    }
    

    Vielleicht k├Ânnt ihr mir ja einen Anhaltspunkt geben wo ich ├╝berhaupt Anfangen muss, weil ich seh schon wieder den Wald vor B├Ąumen nicht mehr ­čś«



  • Hallo ­čÖé

    also zuerst musst du eine iteratorneklasse in der stackklasse anlegen

    class stack
    {
        //...
        class Iterator
        {
            //...
        private:
            list_el *stack_pos;
        };
    };
    

    zu den funktionen des iterators:

    der operator ++ ist ganz einfach, der zeiger wird einfach aufs n├Ąchste element gesetzt

    stack_pos = stack_pos->pnext;
    

    += l├Ąuft in einer schleife einfach immer weiter. wenn zwischendurch der zeiger 0 ist, dann ist ende und das hei├čt fehler.

    insert und erase machen f├╝r mich jetzt keinen sinn, da sie gegen das prinzip eines stacks versto├čen

    mfg templater



  • Hi.
    Nur ein paar Hinweise...

    void Stack<ANY_TYPE>::push(const ANY_TYPE &element) throw (StackError) {    // schiebt Element in den Stack
        list_el *temp = new list_el;    // erstellt neues Listenelement 
        if(temp == NULL)                    // wenn kein Speicher vorhanden ... 
            throw StackError("kein Heapspeicher frei!");
    

    Das ist falsch, da new nicht einfach 0 zur├╝ckliefert im Fehlerfall, sondern eine Exception vom Typ std::bad_alloc wirft.
    Durch die Exception-Spec "throw (StackError)" w├╝rde an der Stelle dann std::unexpected aufgerufen wenn ein std::bad_alloc fliegt, da std::bad_alloc nicht in der Liste der "erlaubten" Exceptions steht - vorausgesetzt der verwendete Compiler unterst├╝tzt Exception-Specs ├╝berhaupt ausreichend vollst├Ąndig.

    1. Ich w├╝rde dir raten ├╝berhaupt keine Exception-Specs zu verwenden. Einzige Ausnahme: Funktionen bei denen immer (=in jeder Implementierung) garantiert werden kann dass sie keinesfalls irgendwelche Exceptions werfen k├Ânnen sollten bzw. d├╝rfen ruhig mit "throw ()" gekennzeichnet werden.

    2. Statt "ANY_TYPE" schreibt man ├╝blicherweise einfach "T", genauso wie man indexvariablen in Schleifen einfach "i" nennt. Hat sich eingeb├╝rgert und wird weithin verstanden.


  • Mod

    Das ist noch nicht alles, was zu Exceptions zu sagen ist. Nicht nur die Speicherallokation kann fehlschlagen, auch die Initialisierung des Nodeobjektes list_el kann fehlschlagen mit einer unbekannten Exception, n├Ąhmlich dann, wenn der Defaultkonstruktor von ANY_TYPE es tut. Gleiches gilt f├╝r die Zuweisung

    temp->data = element;
    

    In diesem Falle haben wir es nicht nur mit einer Verletzung der Exceptionspezifikation zu tun, es kommt noch ein Speicherleck (temp) hinzu. Die Exceptionspezifikation ist folglich falsch und kann gar nicht richtig erfolgen, wenn ANY_TYPE nicht irgendwie eingeschr├Ąnkt ist. Zudem ist die Zuweisung ineffizient, da das list_el::data ggf. erst einmal defaultinitialisert werden muss - zudem schr├Ąnkt es die m├Âglichen ANY_TYPEs unn├Âtig ein, indem eben nur defaultkonstruierbare Typen m├Âglich sind. Das f├╝hrt uns dazu, dass auch list_el nicht einfach eine einfache (POD-)Datenstruktur sein sollte. Zudem ist der Inhalt von list_el ein Implementationsartefakt, das nicht unbedingt im Template Stack definiert werden muss.

    template<class ANY_TYPE>
    class Stack {
    public:
        Stack();  // throw(), lass das void weg, das erzeugt nur Augenkrebs (hat zwar Bjarne erfunden aber C ist schuld)
        ~Stack(); // throw()
        void push(const ANY_TYPE &);
        void top(ANY_TYPE &) const; // StackError ist m├Âglich, aber auch eine (nicht n├Ąher spezifizierbare) Exception wegen Zuweisungsfehler
        void pop(); // hier k├Ânnte ggf. throw() hin, wenn man verlangt, dass der dtor von ANY_TYPE keine Exception wirft (im Dtor sollte man nie werfen)
        bool is_empty() const; // throw()
    private:
        struct list_el;
        list_el *stack_pointer;
    };
    

    damit die Zuweisung verschwindet und wir unser Leckproblem umgehen, kriegt list_el einen Konstruktor

    template<typename T>
    struct Stack<T>::list_el
    {
        list_el(list_el* next, const T& data) : next(next), data(data) {}
        list_el* next;
        T data;
    };
    

    push wird damit trivial

    template <typename T>
    void Stack<T>::push(const T& element) {
        stack_pointer = new list_el( stack_pointer, element );
    }
    

    Der Rest ergibt sich analog.

    Edit: du solltest dir den Destruktor von Stack noch einmal genau anschauen.



  • bei den destruktoren hab ich noch nich so ganz durchgeschnallt.

    template <class T>
    Stack<T>::~Stack(void) {
    	if(stack_pointer->pnext != NULL) {
    		delete stack_pointer;
    		stack_pointer = NULL;
    	}
    }
    

    besser?


  • Mod

    Vermeide Wiederholungen. pop wei├č bereits, wie man richtig Elemente entfernt. Kein Grund, warum der Destruktor das auch noch wissen muss.

    template <class T>
    Stack<T>::~Stack() {
        while ( !is_empty() )
            pop();
    }
    


  • camper schrieb:

    Vermeide Wiederholungen. pop wei├č bereits, wie man richtig Elemente entfernt. Kein Grund, warum der Destruktor das auch noch wissen muss.

    template <class T>
    Stack<T>::~Stack() {
        while ( !is_empty() )
            pop();
    }
    

    ah okay, alles klar.

    wenn ich jetzt in der pop-Funtion den list_el *temp weglassen w├╝rde, w├╝rden die datens├Ątze dann nicht mehr richtig gel├Âscht werden, oder?


  • Mod

    ex.aveal schrieb:

    wenn ich jetzt in der pop-Funtion den list_el *temp weglassen w├╝rde, w├╝rden die datens├Ątze dann nicht mehr richtig gel├Âscht werden, oder?

    wie weglassen?



  • camper schrieb:

    ex.aveal schrieb:

    wenn ich jetzt in der pop-Funtion den list_el *temp weglassen w├╝rde, w├╝rden die datens├Ątze dann nicht mehr richtig gel├Âscht werden, oder?

    wie weglassen?

    folgendes:

    wenn ich anstatt ...

    template <class ANY_TYPE>
    void Stack<ANY_TYPE>::pop(void) throw (StackError) {                // loescht erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        list_el *temp = stack_pointer;
        stack_pointer = stack_pointer->pnext;
        delete temp;
    }
    

    ... nur ...

    template <class ANY_TYPE>
    void Stack<ANY_TYPE>::pop(void) throw (StackError) {                // loescht erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        stack_pointer = stack_pointer->pnext;
    }
    

    schreibe. hoffe ihr checkt was ich mein ­čśâ



  • Hallo,

    da es (auch) kein delete mehr geben w├╝rde, wird auch nichts gel├Âscht. Der stack_pointer zeigt zwar auf das "richtige" Element, aber das nicht mehr ben├Âtigte Element "h├Ąngt" nutzlos im Speicher ("memory leak").

    MfG,

    Probe-Nutzer



  • okay alles klar und danke schonmal!

    habe jetzt folgenden code, schmei├čt aber noch etliche errors und warnings raus. versuche gerade zu debuggen, aber find noch nicht wirklich die fehler. Der Compiler meldet zB eine Neudefinition von iterator bei den Funktionen begin() und end(). also ich versteh ganichts mehr.

    // Stack.h //
    
    #ifndef STACK_H_
    #define STACK_H_
    
    class StackError {			// Exceptionklasse
    public:
    	char *what(void);
    	StackError(char *);
    private:
    	char *error;
    };
    
    StackError::StackError(char *error) {
    	this->error = error;
    }
    
    char *StackError::what(void) {		// Abfrage um welche Exception es sich handelt
    	return error;
    }
    
    template <class T>
    class Stack {
    private:
    	struct list_el;
    	list_el *stack_pointer;
    public:
    	Stack();
    	~Stack();
    	void push(const T &) throw (StackError);
    	void top(T &) throw (StackError);
    	void pop() throw (StackError);
    	bool is_empty();
    	class iterator {			// iterator-Klasse
    	public:
    		iterator(list_el *pos = NULL);
    		void operator++() throw (StackError);
    		void operator+=(const int) throw (StackError);
    		void insert() throw (StackError);
    		void erase() throw (StackError);
    	private:
    		list_el *pElement;				// Zeiger auf Element
    	};
    	iterator begin();
    	iterator end();
    };
    
    ////////////// LISTENELEMENTE //////////////
    
    template <typename T>			// Template fuer Listenelement
    struct Stack<T>::list_el {
    	list_el(list_el *pnext, const T &data) : pnext(pnext), data(data) {}	// Konstruktur
    	list_el *pnext;				// Verkettung
    	T data;						// Daten des Listenelements
    };
    
    ////////////// STACK //////////////
    
    template <class T>
    Stack<T>::Stack(void) {
    	stack_pointer = NULL;
    }
    
    template <class T>
    void Stack<T>::push(const T &element) throw (StackError) {	// schiebt Element in den Stack
    	stack_pointer = new list_el(stack_pointer, element);	// erstellt neues Listenelement
    	if(stack_pointer == NULL)								// wenn kein Speicher vorhanden ...
    		throw StackError("kein Heapspeicher frei!");		// Exception
    }
    
    template <class T>
    void Stack<T>::top(T &element) throw (StackError) {	// liest erstes Element
    	if(is_empty())
    		throw StackError("Stack ist leer!");
    	element = stack_pointer->data;	// gibt erstes Element zurueck
    }
    
    template <class T>
    void Stack<T>::pop(void) throw (StackError) {				// loescht erstes Element
    	if(is_empty())
    		throw StackError("Stack ist leer!");
    	list_el *temp = stack_pointer;					// temp zum loeschen des Elements
    	stack_pointer = stack_pointer->pnext;
    	delete temp;
    	temp = NULL;
    }
    
    template <class T>
    bool Stack<T>::is_empty(void) {
    	if(stack_pointer == NULL)	// prueft ob erstes Element vorhanden
    		return true;
    	else
    		return false;
    }
    
    template <class T>
    Stack<T>::~Stack(void) {
    	while(!is_empty())
    		pop(); 
    }
    
    ////////////// ITERATOR //////////////
    
    template <class T>
    Stack<T>::iterator::iterator(list_el *pos) {
    	pElement = pos;
    }
    
    template <class T>
    void Stack<T>::iterator::operator++(void) {
    	pElement = pElement->pnext;
    	if(pElement == NULL)
    		throw StackError("iterator hinter Stackende geschaltet!");
    }
    
    template <class T>
    void Stack<T>::iterator::operator+=(const int n) {
    	int i;
    	for(i = 0; i >= n; i++) {
    		pElement = pElement->pnext;
    		if(pElement == NULL)
    			throw StackError("iterator hinter Stackende geschaltet!");
    	}
    }
    
    template <class T>
    void Stack<T>::iterator::erase(void) {
    }
    
    template <class T>
    void Stack<T>::iterator::insert(void) {
    }
    
    template <class T>
    iterator Stack<T>::begin(void) {
    	Stack<T>::iterator it(stack_pointer);		// stack_pointer zeigt immer auf erstes Element
    	return it;
    }
    
    template <class T>
    iterator Stack<T>::end(void) {
    	for(;;) {
    		if(pElement->pnext == NULL)				// hangelt sich bis zum letzten element durch
    			Stack<T>::iterator it(pElement);
    		pElement = pElement->pnext;
    		return it;
    	}
    }
    
    #endif // STACK_H_
    

    und hier ist die build dazu, heftig ­čśâ ...

    ------ Erstellen gestartet: Projekt: uebung_09_iteratoren, Konfiguration: Debug Win32 ------
    Kompilieren...
    main.cpp
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(30) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(46): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Stack<T>".
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(31) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(32) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(37) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(34): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Stack<T>::iterator".
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(38) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(39) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(40) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(65) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(72) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(79) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(135) : error C2143: Syntaxfehler: Es fehlt ';' vor 'Stack<T>::begin'
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(135) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterst├╝tzt.
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(141) : error C2143: Syntaxfehler: Es fehlt ';' vor 'Stack<T>::end'
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(141) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterst├╝tzt.
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(141) : error C2086: 'int iterator': Neudefinition
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(135): Siehe Deklaration von 'iterator'
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(30) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(10): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Stack<T>".
    with
    [
    T=float
    ]
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(31) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(32) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(18) : warning C4305: 'Argument': Verk├╝rzung von 'double' in 'const float'
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(20) : warning C4305: 'Argument': Verk├╝rzung von 'double' in 'const float'
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(22) : warning C4305: 'Argument': Verk├╝rzung von 'double' in 'const float'
    c:\eigene dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(24) : error C2065: 'zahl_float': nichtdeklarierter Bezeichner
    Das Buildprotokoll wurde unter "file://c:\Eigene Dateien\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\Debug\BuildLog.htm" gespeichert.
    uebung_09_iteratoren - 6 Fehler, 16 Warnung(en)
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 ├╝bersprungen ==========



  • template <class T>
    Stack::iterator Stack<T>::begin(void)...
    

    So sollte das gehen.


  • Mod

    // Stack.h //
    
    #ifndef STACK_H_
    #define STACK_H_
    
    class StackError {            // Exceptionklasse
    public:
        char *what(void);                                                                                   // dies sollte alles mit const char*
        StackError(char *);                                                                                 // arbeiten, da du hier vorhast, Literale
    private:                                                                                                // zu ├╝bergeben, zudem ist kein sinnvoller Grund erkennbar
        char *error;                                                                                        // weshalb ein Handler den String ver├Ąndern wollte
    };
    
    StackError::StackError(char *error) {                                                                   // bevorzuge die Initialisierungsliste
        this->error = error;                                                                                // ist hier zwar egal, kann aber sonst schnell un├╝bersichtlich werden
    }
    
    char *StackError::what(void) {        // Abfrage um welche Exception es sich handelt                    // Funktion ver├Ąndert das Exception-Objekt nicht -> const
        return error;
    }
    
    // StackError ist simpel genug, dass es k├╝rzer und verst├Ąndlicher wird, wenn du die Funktionenn inline in der Klassendefinition definierst
    
    template <class T>
    class Stack {
    private:
        struct list_el;
        list_el *stack_pointer;
    public:
        Stack();
        ~Stack();
        void push(const T &) throw (StackError);                                                            // die Exceptionspezifikation ist zweifelhaft (h├Ąngt tats├Ąchlich von T ab)
        void top(T &) throw (StackError);                                                                   // dito, gibt logisch einen Wert zur├╝ck, f├╝r Spielereien mit Referenzen gibt es keinen Grund
                                                                                                            // --> const T& top() const   oder  T top() const
                                                                                                            // in ersterem Falle m├╝sste man spezifizieren, ob und wann die Referenz ung├╝ltig wird
                                                                                                            // Funktion ver├Ąndert den Stack nicht -> const
        void pop() throw (StackError);
        bool is_empty();                                                                                    // -> const
        class iterator {            // iterator-Klasse
        public:
            iterator(list_el *pos = NULL);
            void operator++() throw (StackError);                                                           // postfix ++ fehlt
            void operator+=(const int) throw (StackError);                                                  // operator + fehlt (sollte aber freie Funktion bleiben -> ggf. friend oder Bezug auf +=)
            void insert() throw (StackError);                                                               // was macht diese Funktion ?
            void erase() throw (StackError);                                                                // dito
        private:
            list_el *pElement;                // Zeiger auf Element
        };
        iterator begin();                                                                                   // -> const
        iterator end();                                                                                     // -> const
    };
    
    ////////////// LISTENELEMENTE //////////////
    
    template <typename T>            // Template fuer Listenelement
    struct Stack<T>::list_el {
        list_el(list_el *pnext, const T &data) : pnext(pnext), data(data) {}    // Konstruktor
        list_el *pnext;                // Verkettung
        T data;                        // Daten des Listenelements
    };
    
    ////////////// STACK //////////////
    
    template <class T>
    Stack<T>::Stack(void) {                                                                                 // Initialsierungsliste ?
        stack_pointer = NULL;
    }
    
    template <class T>
    void Stack<T>::push(const T &element) throw (StackError) {    // schiebt Element in den Stack
        stack_pointer = new list_el(stack_pointer, element);    // erstellt neues Listenelement
        if(stack_pointer == NULL)                                // wenn kein Speicher vorhanden ...        // das kann niemals passieren
            throw StackError("kein Heapspeicher frei!");        // Exception                                // ^
    }
    
    template <class T>
    void Stack<T>::top(T &element) throw (StackError) {    // liest erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        element = stack_pointer->data;    // gibt erstes Element zurueck
    }
    
    template <class T>
    void Stack<T>::pop(void) throw (StackError) {                // loescht erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        list_el *temp = stack_pointer;                    // temp zum loeschen des Elements
        stack_pointer = stack_pointer->pnext;
        delete temp;
        temp = NULL;                                                                                        // ├╝berfl├╝ssig
    }
    
    template <class T>
    bool Stack<T>::is_empty(void) {
        if(stack_pointer == NULL)    // prueft ob erstes Element vorhanden                                  // bitte
            return true;                                                                                    // nicht
        else                                                                                                // so
            return false;                                                                                   // umst├Ąndlich
    }
    
    template <class T>
    Stack<T>::~Stack(void) {
        while(!is_empty())
            pop();
    }
    
    ////////////// ITERATOR //////////////
    
    template <class T>
    Stack<T>::iterator::iterator(list_el *pos) {                                                            // Initialisierungsliste ?
        pElement = pos;
    }
    
    template <class T>
    void Stack<T>::iterator::operator++(void) {
        pElement = pElement->pnext;
        if(pElement == NULL)
            throw StackError("iterator hinter Stackende geschaltet!");
    }
    
    template <class T>
    void Stack<T>::iterator::operator+=(const int n) {
        int i;
        for(i = 0; i >= n; i++) {                                                                           // du hast bereits op++ geschrieben
            pElement = pElement->pnext;                                                                     // warum alles doppelt ?
            if(pElement == NULL)                                                                            // ruf doch einfach den anderen operator auf
                throw StackError("iterator hinter Stackende geschaltet!");                                  //
        }
    }
    
    template <class T>
    void Stack<T>::iterator::erase(void) {                                                                  // Funktion ?
    }
    
    template <class T>
    void Stack<T>::iterator::insert(void) {                                                                 // Funktion ?
    }
    
    template <class T>
    iterator Stack<T>::begin(void) {                                                                        // iterator ist in Stack<T> verschachtelter Bezeichner -> Stack<T>::iterator
        Stack<T>::iterator it(stack_pointer);        // stack_pointer zeigt immer auf erstes Element        // au├čerdem ist es ein Typ, der von T abh├Ąngt
        return it;                                                                                          // -> typename Stack<T>::iterator Stack<T>::begin() { ...
    }
    
    template <class T>
    iterator Stack<T>::end(void) {                                                                          // dito:  typename Stack<T>::iterator Stack<T>::end() { ...
        for(;;) {
            if(pElement->pnext == NULL)                // hangelt sich bis zum letzten element durch        // etwas stimmt hier nicht...
                Stack<T>::iterator it(pElement);                                                            // Stack<T>:: ist hier nicht notwendig, da wir uns ohnehin im Scope der Klasse befinden
            pElement = pElement->pnext;                                                                     // zudem musst du keine benannte Variable verwenden
            return it;                                                                                      // gib den Wert doch direkt zur├╝ck:  return iterator(pElement)
        }
    }
    
    #endif // STACK_H_
    


  • bekomme mit dem ├╝berarbeiteten code von dir genau die gleichen fehlermeldungen ­čś×

    ------ Erstellen gestartet: Projekt: uebung_09_iteratoren, Konfiguration: Debug Win32 ------
    Kompilieren...
    main.cpp
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(32) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
            d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(51): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Stack<T>".
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(33) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(37) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(42) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
            d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(39): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Stack<T>::iterator".
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(43) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(44) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(45) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(70) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(77) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(84) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(140) : error C2143: Syntaxfehler: Es fehlt ';' vor 'Stack<T>::begin'
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(140) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterst├╝tzt.
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(146) : error C2143: Syntaxfehler: Es fehlt ';' vor 'Stack<T>::end'
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(146) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterst├╝tzt.
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(146) : error C2086: 'int iterator': Neudefinition
            d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(140): Siehe Deklaration von 'iterator'
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(32) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
            d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(10): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "Stack<T>".
            with
            [
                T=float
            ]
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(33) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\stack.h(37) : warning C4290: C++-Ausnahmespezifikation ignoriert, es sei denn, es wird angezeigt, dass eine Funktion nicht __declspec(nothrow) ist
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(18) : warning C4305: 'Argument': Verk├╝rzung von 'double' in 'const float'
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(20) : warning C4305: 'Argument': Verk├╝rzung von 'double' in 'const float'
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(22) : warning C4305: 'Argument': Verk├╝rzung von 'double' in 'const float'
    d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\main.cpp(24) : error C2065: 'zahl_float': nichtdeklarierter Bezeichner
    Das Buildprotokoll wurde unter "file://d:\docs\fh\it4\informatik 3\uebungen\uebung_09_iteratoren\uebung_09_iteratoren\Debug\BuildLog.htm" gespeichert.
    uebung_09_iteratoren - 6 Fehler, 16 Warnung(en)
    ========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 ├╝bersprungen ==========
    

  • Mod

    ex.aveal schrieb:

    bekomme mit dem ├╝berarbeiteten code von dir genau die gleichen fehlermeldungen ­čś×

    Ich habe nichts ├╝berarbeitet, nur kommentiert.



  • ich hab den fehler gefunden!

    template <class T>
    typename Stack<T>::iterator Stack<T>::begin(void) {
        ...
    }
    

    ^^ so funktioniert es jetzt auch. die erase funktion hab ich jetzt auch so ungef├Ąhr hinbekommen, allerdings funktioiniert sie glaub nicht, wenn nur noch ein einziges element im stack ist. die insert funktion wei├č ich einfach nicht wie mein prof haben will, keinen plan.

    // Stack.h //
    
    #ifndef STACK_H_
    #define STACK_H_
    
    class StackError {            // Exceptionklasse
    public:
        char *what(void);
        StackError(char *);
    private:
        char *error;
    };
    
    StackError::StackError(char *error) {
        this->error = error;
    }
    
    char *StackError::what(void) {        // Abfrage um welche Exception es sich handelt
        return error;
    }
    
    template <class T>
    class Stack {
    private:
        struct list_el;
        list_el *stack_pointer;
    public:
        Stack();
        ~Stack();
        void push(const T &) throw (StackError);
        void top(T &) throw (StackError);
        void pop() throw (StackError);
        bool is_empty();
        class iterator {            // iterator-Klasse
        public:
            iterator(list_el *pos);
    		iterator();
            void operator++() throw (StackError);
            void operator+=(const int) throw (StackError);
            void insert(const T &) throw (StackError);
            void erase() throw (StackError);
    		void getit(T &);
        private:
            list_el *pElement;                // Zeiger auf Element
        };
        iterator begin();
        iterator end();
    };
    
    ////////////// LISTENELEMENTE //////////////
    
    template <typename T>            // Template fuer Listenelement
    struct Stack<T>::list_el {
        list_el(list_el *pnext, const T &data) : pnext(pnext), data(data) {}    // Konstruktur
        list_el *pnext;                // Verkettung
        T data;                        // Daten des Listenelements
    };
    
    ////////////// STACK //////////////
    
    template <class T>
    Stack<T>::Stack(void) {
        stack_pointer = NULL;
    }
    
    template <class T>
    void Stack<T>::push(const T &element) throw (StackError) {    // schiebt Element in den Stack
        stack_pointer = new list_el(stack_pointer, element);    // erstellt neues Listenelement
        if(stack_pointer == NULL)                                // wenn kein Speicher vorhanden ...
            throw StackError("kein Heapspeicher frei!");        // Exception
    }
    
    template <class T>
    void Stack<T>::top(T &element) throw (StackError) {    // liest erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        element = stack_pointer->data;    // gibt erstes Element zurueck
    }
    
    template <class T>
    void Stack<T>::pop(void) throw (StackError) {                // loescht erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        list_el *temp = stack_pointer;                    // temp zum loeschen des Elements
        stack_pointer = stack_pointer->pnext;
        delete temp;
        temp = NULL;
    }
    
    template <class T>
    bool Stack<T>::is_empty(void) {
        if(stack_pointer == NULL)    // prueft ob erstes Element vorhanden
            return true;
        else
            return false;
    }
    
    template <class T>
    Stack<T>::~Stack(void) {
        while(!is_empty())
            pop();
    }
    
    ////////////// ITERATOR //////////////
    
    template <class T>
    Stack<T>::iterator::iterator(list_el *pos) {
        pElement = pos;
    }
    
    template <class T>
    Stack<T>::iterator::iterator(void) {
        pElement = NULL;
    }
    
    template <class T>
    void Stack<T>::iterator::operator++(void) {
        pElement = pElement->pnext;
    	if(pElement == NULL)
            throw StackError("iterator hinter Stackende geschaltet!");
    }
    
    template <class T>
    void Stack<T>::iterator::operator+=(const int n) {
        int i;
        for(i = 0; i < n; i++) {
            pElement = pElement->pnext;
    		if(pElement == NULL) {
                throw StackError("iterator hinter Stackende geschaltet!");
    		}
        }
    }
    
    template <class T>
    void Stack<T>::iterator::getit(T &element) {
    	element = pElement->data;
    }
    
    template <class T>
    void Stack<T>::iterator::erase(void) {
    	if(pElement == NULL)
    		throw ("Element nicht vorhanden!");
    	list_el *temp1 = pElement;
    	list_el *temp2;
    	for(;;) {
    		temp2 = temp1->pnext;			// verschiebt die Daten der Elemente ab Iterator ein Element nach vorne
    		temp1->data = temp2->data;
    		if(temp2->pnext == NULL)		// hoere auf, wenn kein weiteres Element mehr exestiert
    			break;
    		temp1 = temp1->pnext;
    	}
    	temp1->pnext = NULL;		// neues Ende makieren
    	delete temp2;				// letztes Element loeschen
    }
    
    template <class T>
    void Stack<T>::iterator::insert(const T &element) {
    	list_el *temp = new list_el(pElement->pnext, element);	// Zeiger auf Neues Element mit pnext auf naechstes Element
    	pElement->pnext = temp;
    }
    
    template <class T>
    typename Stack<T>::iterator Stack<T>::begin(void) {
        Stack<T>::iterator it(stack_pointer);        // stack_pointer zeigt immer auf erstes Element
        return it;
    }
    
    template <class T>
    typename Stack<T>::iterator Stack<T>::end(void) {
    	list_el *temp = stack_pointer;
        for(;;) {												
    		if(temp->pnext == NULL)
    			break;
    		temp = temp->pnext;				// hangelt sich bis zum letzten Element durch
        }
    	Stack<T>::iterator it(++temp);		// ++ -> "HINTER" das letzte Element
    	return it;
    }
    
    #endif // STACK_H_
    

    die main:

    // main.cpp //
    
    #include <iostream>
    #include "Stack.h"
    using namespace std;
    
    int main(void) {
    	float zahl_float;
    	float zahl_float_it;
    
    	int i;
    
    	Stack<float> float_stack;
    	Stack<float>::iterator it;
    	cout << "float_stack erzeugt" << endl;
    
    	try {
    		cout << "is_empty()=" << float_stack.is_empty() << endl;
    		float_stack.push(6.3278);
    		float_stack.push(5.322); 
    		float_stack.push(4.984);
    		float_stack.push(3.1415);
    		float_stack.push(2.563);
    		float_stack.push(1.434);
    		cout << ">>6.3278 >>5.322 >>4.984 >>3.1415 >>2.563 >>1.434" << endl;
    
    		it = float_stack.begin();
    		cout << "begin();" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    
    		++it;
    		cout << "++it;" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    
    		it = float_stack.begin();
    		cout << "begin();" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    
    		it += 2;
    		cout << "it += 2;" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    
    		it.erase();
    		cout << "erase();" << endl;
    		it = float_stack.begin();
    		cout << "begin();" << endl;
    
    		for(i = 0; i < 5; ++i) {
    			it.getit(zahl_float_it);
    			cout << "zahl_float_it=" << zahl_float_it << endl;
    			if(i < 4)
    				++it;
    		}
    
    		it = float_stack.end();
    		cout << "end();" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    
    		it = float_stack.begin();
    		cout << "begin();" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    
    		++it;
    		cout << "++it;" << endl;
    		it.insert(3.3333);
    		cout << "insert(3.3333);" << endl;
    		it = float_stack.begin();
    		cout << "begin();" << endl;
    
    		for(i = 0; i < 6; ++i) {
    			it.getit(zahl_float_it);
    			cout << "zahl_float_it=" << zahl_float_it << endl;
    			if(i < 5)
    				++it;
    		}
    
    		it = float_stack.begin();
    		cout << "begin();" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    		it = float_stack.end();
    		cout << "end();" << endl;
    		it.getit(zahl_float_it);
    		cout << "zahl_float_it=" << zahl_float_it << endl;
    
    		float_stack.top(zahl_float);
    		cout << "<<" << zahl_float;
    		float_stack.pop();
    		float_stack.top(zahl_float);
    		cout << " <<" << zahl_float;
    		float_stack.pop();
    		float_stack.top(zahl_float);
    		cout << " <<" << zahl_float << endl;
    
    		cout << "is_empty()=" << float_stack.is_empty() << endl;
    
    		float_stack.pop();
    		float_stack.top(zahl_float);
    		cout << "<<" << zahl_float;
    		float_stack.pop();
    		float_stack.top(zahl_float);
    		cout << " <<" << zahl_float;
    		float_stack.pop();
    		float_stack.top(zahl_float);
    		cout << " <<" << zahl_float << endl;
    		float_stack.pop();
    
    		cout << "is_empty()=" << float_stack.is_empty() << endl;
    	}
    	catch(StackError err) {
    		cout << err.what() << endl;
    	}
    	return 0;
    }
    


  • Auf den Fehler habe ich und camper dich bereits hingewiesen. (Auch wenn ich bei mir das Template Argument vergessen habe).

    Im ├╝brigen solltest du die Kommentare, die camper dir gegeben hat dennoch mal anschauen, wenn er sich schon die M├╝he macht alles so sch├Ân zu kommentieren.



  • drakon schrieb:

    Auf den Fehler habe ich und camper dich bereits hingewiesen. (Auch wenn ich bei mir das Template Argument vergessen habe).

    Im ├╝brigen solltest du die Kommentare, die camper dir gegeben hat dennoch mal anschauen, wenn er sich schon die M├╝he macht alles so sch├Ân zu kommentieren.

    ich habe die Kommentare von camper sehr wohl durchgelesen, ...

    camper schrieb:

    // Stack.h //
    
    #ifndef STACK_H_
    #define STACK_H_
    
    class StackError {            // Exceptionklasse
    public:
        char *what(void);                                                                                   // dies sollte alles mit const char*
        StackError(char *);                                                                                 // arbeiten, da du hier vorhast, Literale
    private:                                                                                                // zu ├╝bergeben, zudem ist kein sinnvoller Grund erkennbar
        char *error;                                                                                        // weshalb ein Handler den String ver├Ąndern wollte
    };
    
    StackError::StackError(char *error) {                                                                   // bevorzuge die Initialisierungsliste
        this->error = error;                                                                                // ist hier zwar egal, kann aber sonst schnell un├╝bersichtlich werden
    }
    
    char *StackError::what(void) {        // Abfrage um welche Exception es sich handelt                    // Funktion ver├Ąndert das Exception-Objekt nicht -> const
        return error;
    }
    
    // StackError ist simpel genug, dass es k├╝rzer und verst├Ąndlicher wird, wenn du die Funktionenn inline in der Klassendefinition definierst
    

    leider alles vorgaben meines profs.

    camper schrieb:

    template <class T>
    class Stack {
    private:
        struct list_el;
        list_el *stack_pointer;
    public:
        Stack();
        ~Stack();
        void push(const T &) throw (StackError);                                                            // die Exceptionspezifikation ist zweifelhaft (h├Ąngt tats├Ąchlich von T ab)
        void top(T &) throw (StackError);                                                                   // dito, gibt logisch einen Wert zur├╝ck, f├╝r Spielereien mit Referenzen gibt es keinen Grund
                                                                                                            // --> const T& top() const   oder  T top() const
                                                                                                            // in ersterem Falle m├╝sste man spezifizieren, ob und wann die Referenz ung├╝ltig wird
                                                                                                            // Funktion ver├Ąndert den Stack nicht -> const
        void pop() throw (StackError);
        bool is_empty();                                                                                    // -> const
        class iterator {            // iterator-Klasse
    

    ebenfalls alle funktionsr├╝mpfe vorgaben meines profs.

    camper schrieb:

    public:
            iterator(list_el *pos = NULL);
            void operator++() throw (StackError);                                                           // postfix ++ fehlt
            void operator+=(const int) throw (StackError);                                                  // operator + fehlt (sollte aber freie Funktion bleiben -> ggf. friend oder Bezug auf +=)
            void insert() throw (StackError);                                                               // was macht diese Funktion ?
            void erase() throw (StackError);                                                                // dito
        private:
            list_el *pElement;                // Zeiger auf Element
        };
        iterator begin();                                                                                   // -> const
        iterator end();                                                                                     // -> const
    };
    

    sollten nur den pr├Ąfix ++-operator machen sowie den +=, ebenfalls vorgaben des profs. die funktion erase loescht ein element vom stack, auf das der iterator zeigt, insert f├╝gt eins ein. vorgabe vom prof, und ja ich wei├č, dass das den sinn und zweck eines lifo widerspricht.

    camper schrieb:

    ////////////// LISTENELEMENTE //////////////
    
    template <typename T>            // Template fuer Listenelement
    struct Stack<T>::list_el {
        list_el(list_el *pnext, const T &data) : pnext(pnext), data(data) {}    // Konstruktor
        list_el *pnext;                // Verkettung
        T data;                        // Daten des Listenelements
    };
    
    ////////////// STACK //////////////
    
    template <class T>
    Stack<T>::Stack(void) {                                                                                 // Initialsierungsliste ?
        stack_pointer = NULL;
    }
    
    template <class T>
    void Stack<T>::push(const T &element) throw (StackError) {    // schiebt Element in den Stack
        stack_pointer = new list_el(stack_pointer, element);    // erstellt neues Listenelement
        if(stack_pointer == NULL)                                // wenn kein Speicher vorhanden ...        // das kann niemals passieren
            throw StackError("kein Heapspeicher frei!");        // Exception                                // ^
    }
    
    template <class T>
    void Stack<T>::top(T &element) throw (StackError) {    // liest erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        element = stack_pointer->data;    // gibt erstes Element zurueck
    }
    
    template <class T>
    void Stack<T>::pop(void) throw (StackError) {                // loescht erstes Element
        if(is_empty())
            throw StackError("Stack ist leer!");
        list_el *temp = stack_pointer;                    // temp zum loeschen des Elements
        stack_pointer = stack_pointer->pnext;
        delete temp;
        temp = NULL;                                                                                        // ├╝berfl├╝ssig
    

    nicht ├╝berfl├╝ssig, sonst wird das element auf den der stack_pointer gezeigt hat nicht entfernt

    camper schrieb:

    }
    
    template <class T>
    bool Stack<T>::is_empty(void) {
        if(stack_pointer == NULL)    // prueft ob erstes Element vorhanden                                  // bitte
            return true;                                                                                    // nicht
        else                                                                                                // so
            return false;                                                                                   // umst├Ąndlich
    

    wie weniger umst├Ąndlich? bool funktion muss es bleiben, da vorgabe des profs

    camper schrieb:

    }
    
    template <class T>
    Stack<T>::~Stack(void) {
        while(!is_empty())
            pop();
    }
    
    ////////////// ITERATOR //////////////
    
    template <class T>
    Stack<T>::iterator::iterator(list_el *pos) {                                                            // Initialisierungsliste ?
        pElement = pos;
    }
    
    template <class T>
    void Stack<T>::iterator::operator++(void) {
        pElement = pElement->pnext;
        if(pElement == NULL)
            throw StackError("iterator hinter Stackende geschaltet!");
    }
    
    template <class T>
    void Stack<T>::iterator::operator+=(const int n) {
        int i;
        for(i = 0; i >= n; i++) {                                                                           // du hast bereits op++ geschrieben
            pElement = pElement->pnext;                                                                     // warum alles doppelt ?
            if(pElement == NULL)                                                                            // ruf doch einfach den anderen operator auf
                throw StackError("iterator hinter Stackende geschaltet!");                                  //
        }
    }
    
    template <class T>
    void Stack<T>::iterator::erase(void) {                                                                  // Funktion ?
    }
    
    template <class T>
    void Stack<T>::iterator::insert(void) {                                                                 // Funktion ?
    }
    
    template <class T>
    iterator Stack<T>::begin(void) {                                                                        // iterator ist in Stack<T> verschachtelter Bezeichner -> Stack<T>::iterator
        Stack<T>::iterator it(stack_pointer);        // stack_pointer zeigt immer auf erstes Element        // au├čerdem ist es ein Typ, der von T abh├Ąngt
        return it;                                                                                          // -> typename Stack<T>::iterator Stack<T>::begin() { ...
    }
    
    template <class T>
    iterator Stack<T>::end(void) {                                                                          // dito:  typename Stack<T>::iterator Stack<T>::end() { ...
        for(;;) {
            if(pElement->pnext == NULL)                // hangelt sich bis zum letzten element durch        // etwas stimmt hier nicht...
                Stack<T>::iterator it(pElement);                                                            // Stack<T>:: ist hier nicht notwendig, da wir uns ohnehin im Scope der Klasse befinden
            pElement = pElement->pnext;                                                                     // zudem musst du keine benannte Variable verwenden
            return it;                                                                                      // gib den Wert doch direkt zur├╝ck:  return iterator(pElement)
        }
    }
    
    #endif // STACK_H_
    

    usw den rest...



  • ex.aveal schrieb:

    nicht ├╝berfl├╝ssig, sonst wird das element auf den der stack_pointer gezeigt hat nicht entfernt

    Doch, ist wirklich unn├Âtig hier auf NULL zu setzen, noch hinzu kommt, dass temp als lokale Variable sowieso nach dem Ende des G├╝ltigkeitsbereichs nicht mehr zur Verf├╝gung steht.

    MfG,

    Probe-Nutzer



  • wie weniger umst├Ąndlich? bool funktion muss es bleiben, da vorgabe des profs

    Was h├Ąltst du von

    template <class T>
    bool Stack<T>::is_empty(void) {
        return stack_pointer == NULL;
    }
    

    Au├čerdem ist dein Stack<T>::push falsch. new gibt nicht NULL zur├╝ck, sondern wirft eine Exception, wenn kein Speicher mehr verf├╝gbar ist.
    Dadurch dass du die nicht f├Ąngst ist schonmal das throw (StackError) falsch und dein Programm beendet sich einfach.


Log in to reply