Iteratoren - Stack als Klassentemplate - die zweite
-
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.
-
// 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 ==========
-
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.
-
ja okay, is wohl kürzer, werds mal noch ändern.
aber die push funktion funktioniert zumindestens und das programm beendet sich nicht selbst. leider habe ich exceptions noch nicht wirklich behandelt, daher kann ich nicht nachvollziehen was da jetzt falsch sein sollte etc. muss mich da selber erst einarbeiten
Probe-Nutzer schrieb:
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
der erste datensatz bleibt laut meinem prof sonst im speicher und wird erst bei programmende wieder freigegeben. aufdauer würde es sonst eben zum absturz kommen. temp == NULL zu setzen ist nicht zwingend nötig, aber "guter programmier stil" ... wieder laut prof.
aber trotzdem danke nochmal an alle für die hilfe
-
ex.aveal schrieb:
temp == NULL zu setzen ist nicht zwingend nötig, aber "guter programmier stil" ... wieder laut prof.
Dein Prof ist vielleicht ein guter Theoretiker, aber danach hört es auf. Lokale Variablen die nicht mehr verwendet werden (oder auch Membervariablen die nicht mehr verwendet werden) brauchen nicht extra eine Sonderbehandlung.
Besonders schön sind solche unnötigen Codekonstrukte (wo ein "delete zeiger" ausgereicht hätte):
Klassenname::~Klassenname() { if(!zeiger) { delete zeiger; zeiger = 0; } }
So im realen Projekt vorhanden. Und was Programmierstil angeht: Code soll übersichtlich sein, wenn unnötige Zeilen den Code verlängern reduziert dies ebenso die Lesbarkeit wie schlechtes Einrücken.
cu André
-
ex.aveal schrieb:
aber die push funktion funktioniert zumindestens und das programm beendet sich nicht selbst.
Ja, damit sich das Programm beendet, muss auch das allokieren des Speichers fehlschlagen. Vermutlich hast Du diese Situation einfach noch nicht erreicht.
Der Punkt ist aber, dass Dein Programm niemals, also auch nicht wenn die Allokation schiefgeht, einen StackError auslösen kann. Denn diese Form von new liefert niemals NULL als Ergebnis.
-
LordJaxom schrieb:
Denn diese Form von new liefert niemals NULL als Ergebnis.
Doch auf SEHHHR alten Compilern (VC6 und Co.)
Vielleicht sollte sich der Dozent vom OP mal mit den C++ Standard auseinander setzen (Nachdem er nun 10 Jahre draußen ist, und der nächste vor der Tür steht).
cu André
-
und wie würde dann eine lösung des problems aussehen?
wie und was müßte ich denn dann aufrufen?!
-
Das hier sollte so funktionieren, wie du es dir vorgestellt hast:
template <class T> void Stack<T>::push(const T &element) throw (StackError) { try { stack_pointer = new list_el(stack_pointer, element); } catch (std::bad_alloc) { throw StackError("kein Heapspeicher frei!"); } }