Array Stack push
-
Hi, folgendes Programm wird erfolgreich compiliert doch die Ausführung führt zu einem Programmabsturz. Wo liegt der Fehler?
jojo.h
#include <iostream> using namespace std; class chip { public: virtual int zeigdich() const = 0; }; class chip_0 : public chip { public: int zeigdich() const { return 0; } }; class chip_1 : public chip { public: int zeigdich() const { return 1; } }; class chip_2 : public chip { public: int zeigdich() const { return 2; } }; class stack { enum { size = 100 }; int top; chip* feld[size]; public: stack() : top(0) {} class stack_voll {}; void push (chip* ding) throw (stack_voll) { if (top == size) throw stack_voll(); feld[top] = ding; top++; } void zeigdich() { int counter[2]; for (int i=0; i<=2; i++) { counter[i] = 0; } for (int i=0; i<=size; i++) { counter[feld[i]->zeigdich()]++; } for (int i=0; i<=2; i++) { cout << "Von Typ " << i << " vorhanden: " << counter[i] << endl; } } };ausfuehren.cpp
#include "jojo.h" void main() { stack st; try { st.push( new chip_1 ); st.push( new chip_0 ); st.push( new chip_2 ); st.push( new chip_0 ); } catch ( stack::stack_voll ) { cout << "Stack ist voll zefix" << endl; exit(1); } st.zeigdich(); }
-
spotan: dein "feld" ist ein zeiger auf ein array. nimm den stern oder die [] weg.
edit: du musst dein "feld" auch reservieren, also new() dafür aufrufen.
-
ghorst schrieb:
spotan: dein "feld" ist ein zeiger auf ein array. nimm den stern oder die [] weg.
edit: du musst dein "feld" auch reservieren, also new() dafür aufrufen.
Das müsste einen Compile Fehler geben.
Aber ich denke mal, dass er ein ganz anderes Problem hat.
int counter[2];for (int i=0; i<=2; i++)Das kann so nicht gehen. Da greifst du auf Speicher zu, der nicht zu counter gehört.
Du hast in counter genau Platz für 2 integer. Der erste ist 0, der zweite ist 1.
Na was passiert wohl, wenn du jetzt auf [2] zugreifst?
In einem Fall ist geholfen, wenn du das machst:for (int i = 0; i < 2; i++) // Beachte < und nicht <= !
-
drakon schrieb:
Das müsste einen Compile Fehler geben.
warum sollte es einen solchen geben? das ist in c und c++ völlig legal
-
ghorst schrieb:
drakon schrieb:
Das müsste einen Compile Fehler geben.
warum sollte es einen solchen geben? das ist in c und c++ völlig legal
Wenn es ein semantischer Fehler ist, dann muss das der Compiler entdecken. Vielleicht will er ja ein Array von Zeigern auf chip haben. Im übrigen ruft er ja new auf und übergibt den Zeiger der Klasse, wo er den Zeiger in einem Array speichert. Das kann er so ganz gut machen. (Über das schlechtes Design reden wir hier mal nicht)
-
ghorst schrieb:
drakon schrieb:
Das müsste einen Compile Fehler geben.
warum sollte es einen solchen geben? das ist in c und c++ völlig legal
Schau dir den Code nochmals an. In dem Code wird ein Array von Zeigern benötigt. Wenn du nur ein Array von Objekten machst, dann gibt es bei der push Funktion sicher einen Compile-Fehler

@Zeiteisen,
Das was Drakon sagt ist korrekt, aber du solltest auch noch die zwei nachfolgenden for-Schleifen begutachten, die haben genau denselben Fehler. Einfach das<=durch ein<ersetzen.Grüssli
-
drakon schrieb:
ghorst schrieb:
drakon schrieb:
Das müsste einen Compile Fehler geben.
warum sollte es einen solchen geben? das ist in c und c++ völlig legal
Wenn es ein semantischer Fehler ist, dann muss das der Compiler entdecken. Vielleicht will er ja ein Array von Zeigern auf chip haben. Im übrigen ruft er ja new auf und übergibt den Zeiger der Klasse, wo er den Zeiger in einem Array speichert. Das kann er so ganz gut machen. (Über das schlechtes Design reden wir hier mal nicht)
Erzähl mir bitte was über das schlechte Design.
Hab das mit den for Schleifen korrigiert. Das eigentliche Problem ist leider nicht gelöst.
-
Du hast immernoch das gleiche Problem, aber diesmal anderst.
for (int i=0; i<=size; i++) { counter[feld[i]->zeigdich()]++; }Hier wird bei chip_2 2 zurückgegeben. Bei aller lieber zur 2, geht das bei einem Array der Grösse 2 einfach nicht.

Zum Design:
1. Du übergibst den Zeiger, den du per new anforderst an eine Klasse, die den Verwalten soll. Wer soll das den jetzt aufräumen? Deiner Meinung nach ja der User der Klasse, was ihm aber so ohne weiteres nicht (so einfach) möglich ist.2. Du scheinst dich in deinem eigenen Code ja nicht sehr auszukennen und daher kann das gar kein gutes Design sein,wenn der Programmierer selbst da nicht durchblickt.
3. Ich nehme mal an, dass du da ein RTTI System simulieren willst. Das geht aber besser (wenn überhaupt nötig) per dynamic_cast<>.
-
-
drakon schrieb:
Zum Design:
[..]
2. Du scheinst dich in deinem eigenen Code ja nicht sehr auszukennen und daher kann das gar kein gutes Design sein,wenn der Programmierer selbst da nicht durchblickt.Also hat das hier jeder Fragender

Nunja das ist eine Klausuraufgabe mit einigen Lösungsvoraussetzungen.
Und es stürzt immernoch ab... Dennoch danke für die schnellen Antworten.
-
Dem Standard-Stack lässt sich halt nicht so einfach eine Methode "zeigdich" hinzufügen, da man ja nicht über die Elemente im Stack iterieren kann. Und bevor man sich eine Wrapperklasse um den Standard-Stack schreibt, die die Elemente beim Einfügen zählt, kann man sich auch gleich nen eigenen Stack schreiben:
#include <iostream> #include <vector> #include <map> struct foo { virtual int bar() const = 0; }; struct foo_a : foo { int bar() const { return 0; } }; struct foo_b : foo { int bar() const { return 1; } }; struct foo_c : foo { int bar() const { return 2; } }; class foo_stack { public: bool empty() const { return foos.empty(); } void push(foo* f) { foos.push_back(f); } foo* top() { return foos.back(); } void pop() { foos.pop_back(); } size_t size() const { return foos.size(); } friend std::ostream& operator<< (std::ostream& os, const foo_stack& s) { std::map<int, int> count; for(std::vector<foo*>::const_iterator iter = s.foos.begin(), end = s.foos.end(); iter != end; ++iter) { ++count[(*iter)->bar()]; } for(std::map<int, int>::const_iterator iter = count.begin(), end = count.end(); iter != end; ++iter) { os << "Vom Typ " << iter->first << " vorhanden: " << iter->second << std::endl; } return os; } private: std::vector<foo*> foos; }; int main() { foo_stack s; s.push(new foo_a()); s.push(new foo_b()); s.push(new foo_a()); s.push(new foo_c()); std::cout << s; while(!s.empty()) { foo* f = s.top(); s.pop(); delete f; } }
-
Zeiteisen schrieb:
drakon schrieb:
Zum Design:
[..]
2. Du scheinst dich in deinem eigenen Code ja nicht sehr auszukennen und daher kann das gar kein gutes Design sein,wenn der Programmierer selbst da nicht durchblickt.Also hat das hier jeder Fragender

Nunja das ist eine Klausuraufgabe mit einigen Lösungsvoraussetzungen.
Und es stürzt immernoch ab... Dennoch danke für die schnellen Antworten.Das ist auch nicht unsere Aufgabe deinen Code zu verstehen und wir haben ihn ja nicht geschrieben.
Na, wenns ne Aufgabe ist, dann solltest du dich mal ransetzen und mal ein wenig überlgen und den Debugger benutzen. Ich hätte kein Problem das zu lösen und die Fehler zu finden, aber dazu habe ich keine Lust, wenn du selber keine Initiative zeigst.
-
Für die es interessiert:
Die Fehler waren alle in der zeigdich Methode und zwar:korrigierter zeigdich
void zeigdich() { int counter[3]; for (int i=0; i<3; i++) { counter[i] = 0; } for (int i=0; i<top; i++) { counter[feld[i]->zeigdich()]++; } for (int i=0; i<3; i++) { cout << "Von Typ " << i << " vorhanden: " << counter[i] << endl; } }