Programmieren lernen(C++)


Recommended Posts

blablabla

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 von Evilken

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

  • 9 months later...
blablabla

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;
};

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Postinho

hehe ist ein sehr gschissener fehler :D

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 von Taffspeed

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

blablabla

hehe ist ein sehr gschissener fehler :D

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?

:ratlos:

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 ;)

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Postinho

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 von Taffspeed

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

blablabla

tu noch bissl casten

Item* newant = (Item*)new Ant();

So simpel, war ja klar :lol: aber vielen Dank, wird aber eh garantiert nicht das letzte Mal sein, dass ich in dem Thread was schreib :D

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.

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Postinho
wird aber eh garantiert nicht das letzte Mal sein, dass ich in dem Thread was schreib :D

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. :D
na der wird sich freuen, wenn du es selbst richtig gut kannst :D

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

blablabla

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 :D

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 von Evilken

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Amateur

@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]

und

2.) 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äre

ein 2 dimensionales Array (

[Code]Field feld[laenge][laenge][/Code]

) am praktischten. Aber nur meine Meinung :)

bearbeitet von heavybass

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

blablabla

@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]

und

2.) 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äre

ein 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 :davinci:

bearbeitet von Evilken

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Amateur

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 :davinci:

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. :-)

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

blablabla

Ich verstehe, von daher wärs auf jeden Fall gscheiter so. Naja, neue Einheit in C++, dann meld ich mich mal wieder :D :

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?

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

  • 1 month later...
blablabla

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 :D

Diesen Beitrag teilen


Link zum Beitrag
Auf anderen Seiten teilen

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Lädt...


  • Folge uns auf Facebook

  • Partnerlinks

  • Unsere Sponsoren und Partnerseiten

  • Wer ist Online

    • Keine registrierten Benutzer online.