PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Klasse vom Prof. bekommen, aber nur Fehler:


AtTheDriveIn
2006-12-04, 16:25:43
Klassendefinition

#ifndef _GERICHTETERGRAPH1
#define _GERICHTETERGRAPH1
#include <string>
#include <vector>

using namespace std;

class Knoten;
class Kante;

class gerichteterGraph {
protected:
int n,m; // Anzahl Knoten, Kanten
vector<Knoten*> alleKnoten; // Feld aller Knoten
vector<Kante *> alleKanten; // Feld aller Kanten
public:
const static int MAXGRAD=10;
gerichteterGraph(int nn=10, int maxgrad=4,
bool mitkantenbewertung=false,
bool kreisfrei=false); // zuf"allig
gerichteterGraph(char *datei="daten/graph1.dat");
gerichteterGraph(const gerichteterGraph&); // tiefe Kopie
~gerichteterGraph(void);
void ausgeben(char *datei="daten/graph0.dat"); //in Datei
Knoten* nrKnoten(int knr)const;//der Knoten mit Nummer knr
int Knotenzahl() const {return n;}; // Anzahl der Knoten
void knotenausgabe(int bis=50); // sequentiell ausgeben
int neuerKnoten();
int neueKante(int von, int nach, double we=1);
private: // Zuweisung unterbunden
gerichteterGraph& operator=(gerichteterGraph&){}
protected: // Hilfsfunktionen
int Kantenindex(Kante *kante) const; // Index im Feld
int Knotenindex(Knoten *knoten) const; // Index im Feld
void neunummerieren(); // der Knoten im Feld
void zuruecksetzen(void); // aller Hilfsfelder
};



class Knoten {
protected:
int nr; // die Knotennummer, fortlaufend ab 1
Kante *nachbarn; // Liste der abgehenden Kanten
~Knoten(){}; // soll nur vom Graphen geloescht werden
public:
Knoten(int num); // au"ser x,y alles auf Null gesetzt
friend class gerichteterGraph;
int knr(void) const {return nr;}
Kante *erste_Kante() const {return nachbarn;}
public: // Hilfsfelder f"ur einige Algorithmen
// und Anwendungen sowie zur Graphik
bool markiert, markiert2; // zum Markieren
int hnr; double hwert; // Hilfsnummer, Hilfswert
string text; // Zur weiteren Bezeichnung des Knotens
int x,y; // bei Graphik: Position des Knotens in der Ebene
void zuruecksetzen(void); // einiger Hilfsfelder
Kante* Nachbarn() const {return nachbarn;} // mu"s leider sein
};



class Kante {
protected:
Knoten *von;
Knoten *nach;
Kante *naechste; // na"chste in der Nachbarliste
double w; // der Wert bei Kantenbewertung
~Kante(){}; // soll nur vom Graphen geloescht werden
public:
Kante(Knoten *v, Knoten *n, double we=1): von(v), nach(n),
w(we), naechste(0),markiert(0),markiert2(0), text("") {}
friend class Knoten;
friend class gerichteterGraph;
Knoten *vonKnoten() const {return von;}
Knoten *nachKnoten() const {return nach;}
Kante *naechsteKante() const {return naechste;}
void SetzeWert(double wert) { w = wert ;} // Wert der Kante setzen
double Wert() const {return w;} // der Wert dieser Kante
bool markiert, markiert2; // Hilfsfelder f"ur Anwendungen,
string text; // Algorithmen und Graphik
};


#endif


Methoden etc.

#include <fstream>
#include <stdlib.h>
#include <iostream>

#include "ggraph.h" // die Klassendefinitionen

using namespace std;

gerichteterGraph::gerichteterGraph(int nn, int maxgrad,bool mitkantenbewertung,bool kreisfrei)
{ // zuf"allig
int i,j,j1,j2,k,g;
int e=15;
int knr; // aktuelle Kantennummer
Kante *nk; // eine neue Kante

if(maxgrad>MAXGRAD) maxgrad=MAXGRAD;
srand(5*maxgrad*maxgrad+nn);

n=nn; m=0;
alleKnoten.resize(n+1,NULL); // Z"ahlung ab 1
for(i=1;i<=n;++i) alleKnoten[i]= new Knoten(i);
for(i=1;i<=n;++i){ // Konstruktoraufrufe
g=rand()%(maxgrad+1);
if(g>0) {
if(kreisfrei) {
j1=(i+1 <=n ? i+1 : n);
j2= (i+2*g*e <=n ? i+2*g*e : n);
}
else {
j1= (i-g*e > 0 ? i-g*e : 1);
j2= (i+g*e <=n ? i+g*e : n); if(j1==i) j1++;
}
g=(j2-j1+1)/g;
for(k=1;k<=maxgrad && j1<=j2 && g>0;++k) {
nk = new Kante(alleKnoten[i],alleKnoten[j1]);
if(mitkantenbewertung) nk->w=rand()/10000000.;
nk->naechste=alleKnoten[i]->nachbarn;
alleKnoten[i]->nachbarn=nk;
m++;
j1+=rand()%g+1;
if(j1==alleKnoten[i]->nr) j1++;
}
}
}

alleKanten.resize(m+1,NULL);
j=0;
for(k=1;k<=n;++k) {
nk=alleKnoten[k]->nachbarn;
while(nk) {
alleKanten[++j]=nk;
nk=nk->naechste;
}
}
if(kreisfrei) {
// n zuf"allige Vertauschungen
Knoten* hilf;
for(i=1;i<=n;++i) {
int j=rand()%n+1;
if(i!=j) {
hilf=alleKnoten[i];
alleKnoten[i]=alleKnoten[j];
alleKnoten[j]=hilf;
alleKnoten[i]->nr=i;
alleKnoten[j]->nr=j;
}
}
}
} // Ende zuf"allige Erzeugung

// Erzeugung aus Datei

gerichteterGraph::
gerichteterGraph(char *datei){
ifstream ein(datei);
register int i,j;
int vonknoten, nachknoten;
double hilf,wert;
cout << "gelesen wird " << datei << endl;
n=m=0;
// zun"achst Gr"o"se des Graphen bestimmen
for(ein>>hilf;!ein.eof() && hilf!=-9999;ein>>hilf) {
if(hilf==0) n++;
m++;
}
m=(m-4*n)/2 ; // 4 Kopfeintr"age je Knoten: nr,x,y,0

alleKnoten.resize(n+1,NULL); // Z"ahlung ab 1
alleKanten.resize(m+1,NULL);

for(i=1;i<=n; ++i) alleKnoten[i]= new Knoten(i);

ein.clear(); ein.seekg(0); // an den Anfang setzen

for(i=1,j=0;i<=n; ++i){ // j ist Kantenz"ahler
ein >> vonknoten; // Knotennummer eingelesen
if(i!=vonknoten){
cout << " FEHLER: i=" << i
<< ", vonknoten=" << vonknoten <<endl;
exit(1);
} // Koordinaten einlesen
ein >> alleKnoten[i]->x >> alleKnoten[i]->y;
for(ein>>nachknoten; nachknoten!=0; ein>>nachknoten){
ein>>wert;
alleKanten[++j]= new Kante(alleKnoten[i],
alleKnoten[nachknoten],
wert);
// in Nachbarliste eintragen
alleKanten[j]->naechste=alleKnoten[i]->nachbarn;
alleKnoten[i]->nachbarn=alleKanten[j];
}
}
ein.close();
}

// Kopierkonstruktor mit tiefer Kopie
gerichteterGraph::gerichteterGraph(const gerichteterGraph& g){
m=g.m; n=g.n;
alleKnoten.resize(n+1,NULL); // Z"ahlung ab 1
alleKanten.resize(m+1,NULL);
alleKnoten[0]=NULL; alleKanten[0]=NULL; // wichtig!
for(int i=1;i<=n;++i) // Achtung: Konstruktor von Kanoten!
alleKnoten[i]= new Knoten(*(g.alleKnoten[i]));
for(int i=1;i<=m;++i)
alleKanten[i]= new Kante(*(g.alleKanten[i]));
// die Adressen der neuen Kanten werden eintragen:
// mit den jetzt noch eingetragenen alten Adressen
// werden die zugehoerigen Indizes in dem Quellgraphen g
// gesucht; mit diesen Indizes erh"alt man die neuen
// Adressen aus den Feldern des neuen Graphen:
for(int i=1;i<=n;++i)
alleKnoten[i]->nachbarn=
alleKanten[g.Kantenindex(alleKnoten[i]->nachbarn)];
for(int i=1;i<=m;++i) {
alleKanten[i]->naechste=
alleKanten[g.Kantenindex(alleKanten[i]->naechste)];
alleKanten[i]->von=
alleKnoten[g.Knotenindex(alleKanten[i]->von)];
alleKanten[i]->nach=
alleKnoten[g.Knotenindex(alleKanten[i]->nach)];
}
}

gerichteterGraph::~gerichteterGraph(void) {
for(int i=1;i<=n; ++i) delete alleKnoten[i];
for(int i=1;i<=m; ++i) delete alleKanten[i];
}

// der Knoten mit Nummer knr
Knoten* gerichteterGraph::nrKnoten(int knr) const{
int i;
for(i=1; i<=n && alleKnoten[i]->nr!=knr ;++i);
return (i<=n ? alleKnoten[i] : 0);
}

// der Index eines Knoten im Kantenfeld
int gerichteterGraph::Knotenindex(Knoten *knoten) const{
int i;
for(i=1; i<=n && alleKnoten[i]!=knoten ;++i);
return (i<=n ? i : 0);
}

// der Index einer Kante im Kantenfeld
int gerichteterGraph::Kantenindex(Kante *kante) const{
int i;
for(i=1; i<=m && alleKanten[i]!=kante ;++i);
return (i<=m ? i : 0);
}

void gerichteterGraph::knotenausgabe(int bis) {
for(int i=1; i<=n && i<=bis;++i) {
if(i%15==0) cout << endl;
cout << alleKnoten[i]->nr << " ";
}
cout << endl;
}

// Ausgeben des Graphen in eine Datei
void gerichteterGraph::
ausgeben(char *datei){ // in Datei
ofstream aus(datei);
register int i;
cout << "ausgeben" << endl;
Kante *k;
for(i=1;i<=n;++i) {
if(i>1) aus << endl;
aus << alleKnoten[i]->nr
<< " " << alleKnoten[i]->x << " " << alleKnoten[i]->y;
k=alleKnoten[i]->nachbarn;
while(k) {
aus << " " << k->nach->nr << " " << k->w ;
k=k->naechste;
}
aus << " 0";
}
aus << endl;
aus.close();
}

int gerichteterGraph::neuerKnoten() {
alleKnoten.push_back(new Knoten(++n));
return n; // Nummer des neuen Knotens
}

int gerichteterGraph::
neueKante(int von, int nach, double we){
if(von < 1 || von > n ||
nach < 1 || nach > n || von==nach) {
cerr << "Ungueltige Knotennummer bei Kantenerzeugung\n";
exit(1);
} // vonKnoten, nachKnoten
Knoten *vK=alleKnoten[von], *nK=alleKnoten[nach];
for(Kante* ka=vK->erste_Kante();ka!=NULL;ka=ka->naechste)
if(ka->nach==nK) {
cerr << "Kante " << von << "-->" << nach
<< " bereits vorhanden. Doppelkanten verboten\n";
exit(1);
}
Kante* neueK = new Kante(vK,nK,we);
alleKanten.push_back(neueK);
// neue Kante in Nachbarschaftsliste
neueK->naechste=vK->erste_Kante();
vK->nachbarn=neueK;
return ++m; // Kantenzaehler erh"ohen
}

// der Knoten im Feld
void gerichteterGraph::neunummerieren(){
for(int i=1;i<=n;++i) { // aber alte Nummer merken
alleKnoten[i]->hnr=alleKnoten[i]->nr;
alleKnoten[i]->nr=i;
}
}


// aller Hilfsfelder
void gerichteterGraph::zuruecksetzen(void) {
for(int i=1; i<=n; ++i)
alleKnoten[i]->zuruecksetzen();
}


Knoten::Knoten(int num): nr(num), nachbarn(0), text(""),
x((rand()%20)*20+20), y((rand()%20)*20+40) {
zuruecksetzen();
}

void Knoten::zuruecksetzen(void) { // einiger Hilfsfelder
markiert=false; markiert2=false; hwert=0; hnr=0;
}

Ich habe auch eine Zip Datei angehängt.

Unser Prof. hat uns diese beiden Dateien zur Verfügung gestellt um bis nächsten Montag eine Aufgabe zu erledigen.
Ich kann nur nicht mit der Aufgabe anfangen, solange der oben stehende Code fehlerhaft ist. Der Prof. behauptet er könne es compilieren (Unix, g++)

Ich bekomme mit unter Windows mit VS2005 immer folgende Fehlermeldung und habe keine Ahnung woran das liegt.

Fehler 1 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_WinMain@16" in Funktion "___tmainCRTStartup". MSVCRTD.lib


Wenn ihr eine Idee habt, wäre ich euch echt dankbar.

del_4901
2006-12-04, 16:34:06
Der Linker sagt dir doch genau was fehlt. Denk daran das es sich hierbei nur um die Klasse Graph und deren Hilfsklassen handelt!

Sollte man den Fehler immernoch nicht finden würde ich ein Informatikstudium (falls ein solches besteht) lieber an den Nagel hängen.

Coda
2006-12-04, 16:38:55
Es kompiliert doch. Nur linken tuts ned. Warum nur? :D

AtTheDriveIn
2006-12-04, 16:48:54
Ist es denn so schwer einfach zu sagen was falsch ist, wenn es doch anscheinend so offensichtlich ist? :|

Matrix316
2006-12-04, 17:01:47
Im Visual Studio 6 gibts einige Fehler beim Compilieren.

:\testprojektedev\test3d\ggraph.h(17) : error C2258: Ungueltige Syntax fuer rein virtuelle Methode; '= 0' erforderlich
d:\testprojektedev\test3d\ggraph.h(17) : error C2252: 'MAXGRAD' : Nur Funktionen koennen rein virtuell deklariert werden
d:\testprojektedev\test3d\ggraph.h(37) : warning C4520: 'gerichteterGraph' : Mehrere Standardkonstruktoren angegeben

Vielleicht liegts auch nur an der alten Entwicklungsumgebung bei mir. ;) Er meckerte dann auch noch rum weil int i dauernd neu definiert wurde (in den vielen for Schleifen)

del_4901
2006-12-04, 17:05:42
Im Visual Studio 6 gibts einige Fehler beim Compilieren.

:\testprojektedev\test3d\ggraph.h(17) : error C2258: Ungueltige Syntax fuer rein virtuelle Methode; '= 0' erforderlich
d:\testprojektedev\test3d\ggraph.h(17) : error C2252: 'MAXGRAD' : Nur Funktionen koennen rein virtuell deklariert werden
d:\testprojektedev\test3d\ggraph.h(37) : warning C4520: 'gerichteterGraph' : Mehrere Standardkonstruktoren angegeben

Vielleicht liegts auch nur an der alten Entwicklungsumgebung bei mir. ;) Er meckerte dann auch noch rum weil int i dauernd neu definiert wurde (in den vielen for Schleifen)

Ihh, installier dir bitte VS 2005, das VS6 kannst du an den Nagel hängen. Ich hab auch mal gedacht VS6 ist das Obergeilste, Oberbeste ... aber mit dem neuen hat sich das geändert.

Gast
2006-12-04, 17:06:55
Ich hab es gerade mit Dev-C++ unter Windows kompiliert. Geht einwandfrei. Ist aber auch der GCC-Compiler.

Matrix316
2006-12-04, 17:13:45
Ihh, installier dir bitte VS 2005, das VS6 kannst du an den Nagel hängen. Ich hab auch mal gedacht VS6 ist das Obergeilste, Oberbeste ... aber mit dem neuen hat sich das geändert.Ich arbeite hier aber mit älteren Programmen die (laut ersteller) nicht mit dem neuen kompatibel sind. Ich habe auch nur die Express Edition hier - und das ist doch jetzt alles nur noch .NET, oder kann ich auch MFC Programme erstellen / übernehmen? :| :confused:

BTW. @ AtTheDriveIn

Du hast jetzt schon ein eigenes Programm, in dem du die Klasse includierst, compiliert?

Trap
2006-12-04, 17:15:50
Ich habe auch nur die Express Edition hier - und das ist doch jetzt alles nur noch .NET, oder kann ich auch MFC Programme erstellen? :| :confused:
Nein und Ja (ob MFC mit der EE geht weiß ich nicht sicher, mit einer der Bezahlversionen gehts). Trotzdem sind VS2005 und VC6 inkompatibel, das liegt hauptsächlich daran, dass VC6 zu C++ inkompatibel ist.

Gast
2006-12-04, 17:17:25
Ich arbeite hier aber mit älteren Programmen die (laut ersteller) nicht mit dem neuen kompatibel sind. Ich habe auch nur die Express Edition hier - und das ist doch jetzt alles nur noch .NET, oder kann ich auch MFC Programme erstellen / übernehmen? :| :confused:

BTW. @ AtTheDriveIn

Du hast jetzt schon ein eigenes Programm, in dem du die Klasse includierst, compiliert?

Ich glaube nicht, sonst wuerde wohl nicht der Linkererror Win[b]Main[b/] kommen.

Matrix316
2006-12-04, 17:25:16
Stimmt. Aber wenn ich die (von VS6 :rolleyes: ) angezeigten Fehler korrigiere, kann ichs kompilieren. Irgendwas mit den Linkereinstellungen stimmt anscheinend nicht. ;)

tokugawa
2006-12-04, 17:47:10
Unser Prof. hat uns diese beiden Dateien zur Verfügung gestellt um bis nächsten Montag eine Aufgabe zu erledigen.
Ich kann nur nicht mit der Aufgabe anfangen, solange der oben stehende Code fehlerhaft ist. Der Prof. behauptet er könne es compilieren (Unix, g++)

Ich bekomme mit unter Windows mit VS2005 immer folgende Fehlermeldung und habe keine Ahnung woran das liegt.

Fehler 1 error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_WinMain@16" in Funktion "___tmainCRTStartup". MSVCRTD.lib


Wenn ihr eine Idee habt, wäre ich euch echt dankbar.

Der Code ist nicht fehlerhaft, sondern dein Projekt wo du diesen Code einbindest, ist fehlerhaft.

Ich vermute du hast kein "Hauptprogramm" erzeugt, sprich, irgendwo einen Programmeinsprungspunkt (WinMain(); oder, wenn du eine Win32 Konsolenanwendung erzeugst, main()) erzeugt.

Du kannst klarerweise kein Programm kompilieren das kein "Programm" ist, sprich, das keinen definierten Startpunkt hat.

Mach dir bitte im Visual Studio eine generische Win32-Anwendung. Die kommt mit einem kompletten main() bzw. WinMain().

Danach kannst du die Klasse vom Prof hinzufügen und ohne Probleme kompilieren.

Nochmal: der Fehler liegt nicht im Code vom Prof.

Juerg
2006-12-04, 19:39:59
Google First Hit :uponder: :crazy2: :uidea: :whisper: http://www.google.de/search?q=_WinMain@16+___tmainCRTStartup

AtTheDriveIn
2006-12-04, 22:32:39
Nochmal: der Fehler liegt nicht im Code vom Prof.

Der Prof hatte mehrere Fehler in seinem Code, die aber auf einen alten Compiler zurückzuführen waren. Die oben beschriebene war die letzte Fehlermeldung die ich hatte.

Ich hatte auch irgendwann vorher mal testweise eine main() mit in die Methoden-Datei geschrieben, das wollte er aber auch nicht. Ob er da ebenfalls den LNK Error hatte weiß ich jetzt gar nicht mehr. Auf jeden Fall bin ich wohl blind davon ausgegangen das die Fehlermeldung vielleicht wieder mit einem älteren Compiler zu tun hat.




Ich komme gerade von der Arbeit und hab mir die Sache da nochmal durch den Kopf gehen lassen... Main() fehlt, ich idiot :D Studium an den Nagel hängen werde ich deswegen aber sicher nicht, AlphaTier