Evilken blablabla Geschrieben 3. Februar 2012 (bearbeitet) Der Debugger zeigt mir einen Segmentation Fault mit dem Fehler 0x804863f und speicher habe ich vorhin auch bereits erzeugt (da soll ich einfach einen Pointer zurückgeben lassen, der auf die Matrix zeigt): double** NewMatrix (int zeilen, int spalten) { int i; double** arr = (double**) malloc(zeilen*sizeof(double*)); if(arr==NULL) { return NULL; } for(i=0;i<zeilen;i++) { arr[i]=(double*) malloc(spalten*sizeof(double)); if(arr[i]==NULL) { for( ;i!=0;i--) { free(arr[i-1]); } free(arr); return NULL; } } return arr; } Hast du da den Speicher entsprechend erzeugt? Bzw schau mal i,j an in welchem Umlauf es dich aufhaut Abgesehen davon: double pointer reicht zum Übergeben, nachdem du sowieso Zeiger übergibst. Und persönlich mappe ich zweidimensionale Felder/Matrizen immer auf einen eindimensionalen Array. Da hab ich jetzt den dritten * weggegeben und in der main-Funktion den Adressoperator im Funktionsaufruf entfernt, kann mir aber ehrlich gesagt nicht erklären, warums jetzt funktioniert... jedenfalls danke! bearbeitet 3. Februar 2012 von Evilken 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Evilken blablabla Geschrieben 28. November 2012 Mein Lieblingsthread wird mal wieder hochgeholt: Nachdem ich letzte Woche schon fast durchgedreht bin, da mein Debugger die ganze Zeit beim C++-Programm irgendeinen Blödsinn angezeigt hat und die Lösung einfach nur so simpel war, geh ich jetzt da auch davon aus, komm aber nicht drauf. #include <iostream> #include "Item.h" class Factory{ private: Factory(); ~Factory(); public: static Factory* createInstance() { static Factory* instance; // prüfen, gibt es schon ein Factory if(instance==NULL) { instance = new Factory; }; return (instance); }; Item* createAnthill() { Item* newanthill = new Anthill; return newanthill; }; Item* createAnt() { Item* newant = new Ant; return newant; }; Item* createFood() { Item* newfood = new Food; return newfood; }; }; Konkret geht es jetzt darum, dass mir mein Debugger anzeigt, dass in den Zeilen mit "Item* newAnt = new Ant;" etc. ein Bezeichner bei Ant/Anthill/Food fehlt. Wenn man da jetzt beispielsweise die Ant.h herausgreift: #include <iostream> #include "Item.h" using namespace std; class Ant : public Item{ public: Ant(); ~Ant(); virtual void act(void) { cout << "Act-Methode von Ant"; }; }; , dann sieht man, dass Ant ja eine abgeleitete Klasse von Item ist und das das eigentlich schon erkennen sollte, in meinen Augen. Vielleicht kommt von euch wer drauf, woran das liegen könnte, dass da immer ein Fehler ist... Die Item.h sähe so aus: #include <iostream> #include <list> class Item{ public: Item(); ~Item(); virtual void act(void) = 0; }; 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Taffspeed Postinho Geschrieben 29. November 2012 (bearbeitet) hehe ist ein sehr gschissener fehler Item* createAnt() { Item* newant = new Ant(); return newant; }; aja ver-const-e deine methoden (oder falls du sie sowieso auch ohne einer instance von der klasse brauchst, gleich static), ist zu deiner (code-)sicherheit kennst du shared-ptr/smart-ptr aus der boost (www.boost.org)? hilft gewaltig bei der pointer-"verwaltung" bearbeitet 29. November 2012 von Taffspeed 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Evilken blablabla Geschrieben 29. November 2012 hehe ist ein sehr gschissener fehler Item* createAnt() { Item* newant = new Ant(); return newant; }; Hmm, ja teilweise is der Fehler jetzt weg. Hab dann noch die Ant.h etc. in der Factory.h included. Jetzt zeigt er mir allerdings an, dass "Ein Wert vom Typ "Anthill*" kann nicht zum Initialisieren einer Entität vom Typ "Item*" verwendet werden. Aber is doch a abgeleitete Klasse, da sollt das doch funktionieren? aja ver-const-e deine methoden (oder falls du sie sowieso auch ohne einer instance von der klasse brauchst, gleich static), ist zu deiner (code-)sicherheit kennst du shared-ptr/smart-ptr aus der boost (www.boost.org)? hilft gewaltig bei der pointer-"verwaltung" Bin noch recht neu im programmieren von C++, aber schaus mir mal an, danke 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Taffspeed Postinho Geschrieben 29. November 2012 (bearbeitet) Hmm, ja teilweise is der Fehler jetzt weg. Hab dann noch die Ant.h etc. in der Factory.h included. Jetzt zeigt er mir allerdings an, dass "Ein Wert vom Typ "Anthill*" kann nicht zum Initialisieren einer Entität vom Typ "Item*" verwendet werden. tu noch bissl casten Item* newant = (Item*)new Ant(); Bin noch recht neu im programmieren von C++, aber schaus mir mal an, danke für deine übungen wirds egal sein. der vorteil an solchen "pointern" ist, dass man sich um das delete nicht mehr kümmern braucht. bearbeitet 29. November 2012 von Taffspeed 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Evilken blablabla Geschrieben 29. November 2012 tu noch bissl casten Item* newant = (Item*)new Ant(); So simpel, war ja klar aber vielen Dank, wird aber eh garantiert nicht das letzte Mal sein, dass ich in dem Thread was schreib für deine übungen wirds egal sein. der vorteil an solchen "pointern" ist, dass man sich um das delete nicht mehr kümmern braucht. Interessant, in der Zukunft werd ichs sicher mal brauchen können. 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
StepDoWn Captain Awesome Geschrieben 29. November 2012 Bwuäh, geb auch grad nem Studienanfänger in C Nachhilfe ... da ich mit C# und Java gelernt hab, hab ich null Ahnung von Pointern, händischem Memory Management, usw. ... relativ zach. 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Taffspeed Postinho Geschrieben 29. November 2012 wird aber eh garantiert nicht das letzte Mal sein, dass ich in dem Thread was schreib nur rein damit Bwuäh, geb auch grad nem Studienanfänger in C Nachhilfe ... da ich mit C# und Java gelernt hab, hab ich null Ahnung von Pointern, händischem Memory Management, usw. ... relativ zach. na der wird sich freuen, wenn du es selbst richtig gut kannst 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
StepDoWn Captain Awesome Geschrieben 29. November 2012 na der wird sich freuen, wenn du es selbst richtig gut kannst Nojo, er hat Probleme mit den Basics usw, bzw Code erklären kann ich ihm eh. Für den Moment reichts ... 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Evilken blablabla Geschrieben 30. November 2012 (bearbeitet) Das ganze soll ja so eine recht beliebte Ameisensimulation werden. Dazu hab ich mal ein "Spielfeld" mit einzelnen Felder initialisiert. Zusätzlich brauch ich auch noch eine act-Funktion für später, dass sich die Ameisen, das Essen etc. mal am Spielfeld platziert und sich dann später bewegt (zumindest die Ameisen). Die act-Methode gibt quasi einen Rundenbetrieb wieder. Als Test, da diese Methode zurzeit ja noch nichts macht, außer brav das Spielfeld abzugrasen, geb ich einfach mal einen "Sprung" bei jedem einzelnen Feld aus. Ich war mal recht bequem und habs zurzeit nur quadratisch (muss ich eh noch ändern), hieße, wenn ich Seitenlänge 2 habe, dann sollte 4 mal der Sprung dastehen. Mir fehlt allerdings immer der letzte, komm aber nicht drauf, wo da der Denkfehler wär. Vielleicht ist ja wem fad Das wäre die Erstellung des Spielfelds und unten die Act-all-Methode. Die act-Methode, die dann wirklich den "Sprung ausgibt", ist eine Field-Methode. static Environment* getinstance(unsigned int laenge) { // Environment neu erstellen static Environment* instance; if(instance==NULL) { // ist bereits eine Instanz vorhanden? instance=new Environment; }; Field* _new; _new = new Field(1); instance->start = _new; instance->width = instance->height = 1; if(laenge>1) { instance->expand(laenge-1,0); }; if(laenge>1) { instance->expand(laenge-1,1); }; return instance; // erstelltes Environment zurückgeben } Field* expand(unsigned int size,int direction) { // das Feld nach Süden und Osten erweitern, dass die nötige Größe zustande kommt Field* area_calc; Field* start_area; Field* temp; if(direction==0) { while(size>0) { area_calc = this->get_environment(); while(area_calc->get_south()!=NULL) { area_calc = area_calc->get_south(); }; start_area = new Field(1); start_area->set_north(area_calc); // Norden und Süden zuweisen area_calc->set_south(start_area); if(start_area->get_north()->get_west()!=NULL) { temp=start_area->get_north()->get_west()->get_south(); start_area->set_west(temp); temp->set_east(start_area); }; size--; }; area_calc = this->get_environment(); if(area_calc->get_west()==NULL && area_calc->get_north()==NULL) { return area_calc; }; }; unsigned int down=size; if(direction==1) { while(size>0) { area_calc = this->get_environment(); // Startfeld auswählen while(area_calc->get_east()!=NULL) { area_calc=area_calc->get_east(); }; start_area = new Field(1); // neues Einzelfeld erzeugen start_area->set_west(area_calc); // Westen und Osten zuweisen area_calc->set_east(start_area); this->expand(down,2); size--; }; area_calc=this->get_environment(); if(area_calc->get_west()==NULL && area_calc->get_north()==NULL) { return area_calc; }; }; }; Field* get_environment() { // gibt das Startfeld zurück return (this->start); }; void act_all (int counter) { if(counter<1) { return; }; Field* act_area = get_environment(); // Startfeld wird aufgerufen Field* area_help = act_area; while (act_area!=NULL) { // reihenweises durchgehen von oben nach unten while(act_area!=NULL) { act_area->act(counter); // Area-act wird aufgerufen act_area = act_area->get_east(); // die Area geht eins nach Osten und ruft anschließend wieder die act auf }; act_area = area_help->get_south(); // Reihe ist fertig, Startfeld geht eins nach Süden und startet wieder area_help = act_area; }; }; Das wär dann die act-Methode mit der Sprung-Ausgabe: void act (int counter) { // act-Funktion in der Area (geht durch die Liste) int i; static int feld = 1; for(i=1;i<=counter;i++) { cout << " Jump " << i ; if(i==2) { cout << " Feld " << feld << endl; feld++; }; }; }; Wenn ich das dann mit einer Größe von 2 (also 4 Feldern ausführe) gibt er nur folgendes aus, das 4. Feld fehlt irgendwie: Jump 1 Jump 2 Feld 1 Jump 1 Jump 2 Feld 2 Jump 1 Jump 2 Feld 3 Ich weiß, schaut nicht besonders elegant aus, geht aber jetzt auch nur darum, das ganze zu testen. bearbeitet 30. November 2012 von Evilken 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
heavybass Amateur Geschrieben 30. November 2012 (bearbeitet) @evilken Das Problem ist Zeile this->expand(down,2);[/Code]Durch den 2er wird dann kein neues Field hinzugefügt und dein Feld besteht insgesamt nur aus 3 Fields .Du musst 2 Sachen ändern:1.) Den 2er durch 0 ersetzen, also [Code]this->expand(down,0);[/Code] und2.) Die Zeile [Code]area_calc = this->geht_environment();[/Code] durch [Code]area_calc = this;[/Code] ersetzen (im ersten if Zweig). Andernfalls wird immer nur die 1. Spalte nach Süden verlängert und nicht die östlicheren.Außerdem funktioniert die Methode nicht wenn das Feld schon einmal expandiert wurde.Also zb:[Code] this->expand(2,0); this->expand(2,1); // und dann this->expand(1,0); this->expand(1,1);[/Code]Da du solange nach Osten gehst bis [Code]getSouth()==null; [/Code] ist, werden die Spalten dazwischen, die man auch verlängern müsste, nicht angetastet.Allgemein find ich deine gewählte Datenstruktur ein bissi umständlich. Wenn Du das Spielfeld nicht dynamisch verändern willst wäreein 2 dimensionales Array ([Code]Field feld[laenge][laenge][/Code]) am praktischten. Aber nur meine Meinung bearbeitet 30. November 2012 von heavybass 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Evilken blablabla Geschrieben 1. Dezember 2012 (bearbeitet) @evilken Das Problem ist Zeile this->expand(down,2);[/Code]Durch den 2er wird dann kein neues Field hinzugefügt und dein Feld besteht insgesamt nur aus 3 Fields .Du musst 2 Sachen ändern:1.) Den 2er durch 0 ersetzen, also [Code]this->expand(down,0);[/Code] und2.) Die Zeile [Code]area_calc = this->geht_environment();[/Code] durch [Code]area_calc = this;[/Code] ersetzen (im ersten if Zweig). Andernfalls wird immer nur die 1. Spalte nach Süden verlängert und nicht die östlicheren.Außerdem funktioniert die Methode nicht wenn das Feld schon einmal expandiert wurde.Also zb:[Code] this->expand(2,0); this->expand(2,1); // und dann this->expand(1,0); this->expand(1,1);[/Code]Da du solange nach Osten gehst bis [Code]getSouth()==null; [/Code] ist, werden die Spalten dazwischen, die man auch verlängern müsste, nicht angetastet.Allgemein find ich deine gewählte Datenstruktur ein bissi umständlich. Wenn Du das Spielfeld nicht dynamisch verändern willst wäreein 2 dimensionales Array ([Code]Field feld[laenge][laenge][/Code]) am praktischten. Aber nur meine Meinung Ma vielen Dank, jetzt gehts! Der 2er beim expand ist mal reingerutscht, weil ich umständlicherweise eine weitere if-Anweisung für die direction schreiben wollte, das dann allerdings wieder verworfen hab und dann den 2er nicht wieder ausgetauscht hab. Aber jetzt funktionierts so Zum Array:War auch ein Lösungsansatz von uns, der Lehrbeauftragte hat uns dann aber geraten, dass wir das ganze Spielfeld in der Art und Weise lösen sollen. Naja, solangs den Zweck erfüllt.Edit:Da hab ich ja noch einiges nachzuholen in den Weihnachtsferien vor der Klausur bearbeitet 1. Dezember 2012 von Evilken 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
heavybass Amateur Geschrieben 3. Dezember 2012 Zum Array: War auch ein Lösungsansatz von uns, der Lehrbeauftragte hat uns dann aber geraten, dass wir das ganze Spielfeld in der Art und Weise lösen sollen. Naja, solangs den Zweck erfüllt. Edit: Da hab ich ja noch einiges nachzuholen in den Weihnachtsferien vor der Klausur Es kommt immer auf die Anforderungen an. Wenn ich weiss das sich zB die größe der Datenstruktur während der Laufzeit mehrmals verändern wird, nehm ich natürlich irgendwas mit pointer damit ich mir die herumkopiererei spare. Wenn ich weiss, das sich die Struktur zur Laufzeit nicht andern wird - sondern nur die Inhalte - dann werd ich was statisches, wie zB ein array, nehmen. In deinem Fall macht mMn ein Array Sinn, wenn die Größe des Spielfelds nicht verändert wird. Den einzigen Vorteil in der Verwendung von Pointer sehe ich in dem Fall nur darin, das man sich beim Wechsel von einem Feld zu einem Nachbarfeld min. eine Addition/Subtraktion spart, da du ja den Pointer darauf hast (und bei der Array Lösung musst die Indizes berechnen). Sonst seh ich keinen Grund (angenommen das das Spielfeld gleich bleibt), warum man sich mit Pointer herumärgern sollte. Wahrscheinlich will euer Lehrer das ihr mit Pointer umgehen könnts. :-) 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Evilken blablabla Geschrieben 10. Dezember 2012 Ich verstehe, von daher wärs auf jeden Fall gscheiter so. Naja, neue Einheit in C++, dann meld ich mich mal wieder : Ich soll jetzt einen Ameisenhügel auf dem Spielfeld platzieren. Dazu gehe ich zuerst in die Mitte, dann platziere ich ihn (könnte ich natürlich auch auf irgendeiner Zufallsposition machen, dazu bin ich aber jetzt zu faul). void place_initial(unsigned int ant, unsigned int food) { Field* middle = this->get_environment(); for(int i=1;i<=((this->height)/2);i++) { middle = middle->get_south(); }; for(int j=1;j<=((this->width)/2);j++) { middle = middle->get_east(); }; middle->place_anthill(); this->increase_anthill(); for(int i=1;i<=ant;i++) { middle->place_ant(); this->increase_ant(); }; }; void place_anthill(){ Item* Anthill; Factory* tmp_anthill = Factory::createInstance(); Anthill = tmp_anthill->createAnthill(); [b] this->items->push_back(Anthill);[/b] }; Bei "this->items->push_back(Anthill);" zeigt es mir an, dass "Keine Instanz von Überladene Funktion "std::list<_Ty, _Ax>::push_back[mit _Ty=Item *, _Ax=std::allocator<Item *>] stimmt mit der Argumentliste überein." So habe ich die Variable items in Field definiert: list<Item*> * items; Was hab ich falsch gemacht? 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Evilken blablabla Geschrieben 11. Januar 2013 So, it's me again. Der vorherige Fehler ist auf einmal verschwunden, keine Ahnung warum. 1. ich soll mal eine Liste durchgehen und da die Typen abfragen: for(i=1;i<=counter;i++) { list<Item*>::const_iterator act_iterator; for (act_iterator = this->items->begin(); act_iterator != items->end(); ++act_iterator) { cout << *act_iterator; }; }; Ich hätte vor "cout << *act_iterator;", dann etwas eingefügt, wo ich abfrage, was für ein Typ das Listenelement ist, kann bei mir ja entweder Ameise, Essen oder Ameisenhügel sein. Das hätte ich irgendwie mit getType() versucht, hat aber leider ned funktioniert. Bzw. ich hätte auch einfach nur "act_iterator.act(counter)" ausgeführt, damit auch diese Listenelemente die Bewegungen etc. durchführen, weiß allerdings jetzt nicht, wie ich das implementieren soll. Das erkennt er bei mir nicht. Ok 2. gibts jetzt dann doch ned 0 Zitieren Diesen Beitrag teilen Link zum Beitrag Auf anderen Seiten teilen More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.