Textdatei einlesen und trennen...



  • Also vielleicht wäre es noch interessant wenn du uns die Defintionen deiner Typen "pfeil" und "knoten" mitlieferst. 😉
    Weiterhin ist das atio() nicht gerade die Variante wie man es in C++ macht, schau dazu mal im FAQ da gibt es einen Thread "Einmal Zahl nach String und zurück"(oder so ähnlich) da wird beschrieben wir du besser castest.



  • ich bin gerade auf der arbeit deshalb kann ich die definitionen jetzt nicht mit anpinnen sry, aber die bestehen eh nur aus jeweils einem constructor für jede klasse.

    für den pfeil nimmt der constructor alpha, omega und das gewicht (also anfang, ende und die strcke sozusagen) und beim knoten einfach nur die nr. und den namen.
    die klassen und die jewiligen header-dateien heißen knoten und pfeil.

    das mit dem casten werde ich dann heute noch verändern, wenn es nicht so schön ist... danke für den tip. hier in der FAQ steht tatsächlich solch ein beitrag: http://www.c-plusplus.net/forum/viewtopic-var-t-is-39488.html, schön dieser service 😉



  • Vielleicht wäre für dich auch noch interessant zu wissen, das der Container std::map. dir das speichern von Schlüssel-Wertpaaren erleichtert.Dann kannst du da auch eventuell deinen Knoten mit seiner ID abspeicher.



  • ich komme nicht weiter 😞
    ich kann jetzt meine knoten und kanten erstellen, allerdings weiß ich nicht wie ich diese jetzt sinnvoll in einen container (map???, vektor + linklist???) speichern soll...

    hier mal was ich bisher habe:

    // importExport.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include <stdafx.h>
    #include <cstdlib>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <map>
    #include <string>
    #include "knoten.h"
    #include "pfeil.h"
    
    using namespace std;
    
    ifstream inFileKnoten;
    ifstream inFilePfeil;
    /*ofstream inFileOut;*/
    ofstream outFile;
    
    /*takes filename from stdin and trys to open file*/
    void openFile();
    /*writes output file*/
    void writeToFile();
    void stringToInt(string &);
    void trimString(string &);
    
    int main(){
        openFile();
        writeToFile();
    	getchar();
        return 0;
    }
    
    void openFile(){
    
        inFileKnoten.open("knoten.txt");
        if(inFileKnoten.fail()){
            char c;
            cerr << "Fehler: Datei knoten.txt konnte nicht geöffnet werden\n" << endl;
            cin >> c;
        }
    
    	inFilePfeil.open("pfeile.txt");
    	if(inFilePfeil.fail()){
            char c;
            cerr << "Fehler: Datei pfeile.txt konnte nicht geöffnet werden\n" << endl;
            cin >> c;
        }
    }
    
    void writeToFile(){
        //cout << "Ich schreibe die TextDatei..." << endl;
    
    	//creation of the knoten--------------------------------
    	string c;
    
        while(getline(inFileKnoten,c)){
    		//remove spaces
    		trimString(c);
    
    		//the semikolon as an indicator
    		int pos = c.find(";");
    
    		//find the word in the stringline
    		string name = c.substr(pos+1);
    
    		//find the number in the stringline
    //to-DO change the cast!!!
    		int number = atoi(c.substr(0,pos).c_str());
    
    		//create the knoten
    		knoten myFirstKnoten = knoten(number,name);
    
    		cout << "my knoten: " << myFirstKnoten.print() << endl;
        }
    	//END creation of the knoten--------------------------------
    
    	//creation of the pfeil--------------------------------
    	string s;
    
        while(getline(inFilePfeil,s)){
    		trimString(s);
    
    		//the semikolon as an indicator
    		int pos = s.find(";");
    		int pos2 = s.find_last_of(";");
    
    		//find alhpa and omega and weight
    //to-DO change the cast!!!
    		int alpha = atoi(s.substr(0,pos).c_str());
    		int omega = atoi(s.substr(pos + 1, pos2).c_str());
    		int gewicht = atoi(s.substr(pos2 + 1, s.length()).c_str());
    
    		pfeil myPfeil = pfeil(alpha, omega, gewicht);
    		cout << "my kanten: " << alpha << " " << omega << " " << gewicht << endl;
    	}
    
    	//END creation of the knoten--------------------------------
    }
    
    //removes the spaces out of the string
    void trimString(string &str) {
    	for (int i=0; i < str.length(); i++)
    		if (str[i] == ' ') {
    			str.erase(i,1);
    			i--;
    		}
    }
    

    und hier die pfeil(kanten) und die knoten klassen, die jeweils einen header dazu haben

    #include "stdafx.h"
    #include "pfeil.h"
    #include <cstdio>
    
    using namespace std;
    
    int alpha;
    int omega;
    int gewicht;
    
    pfeil::pfeil()
    :alpha(0), omega(0), gewicht(0)
    {
    }
    
    pfeil::pfeil(int alp, int om, int gew)
    :alpha(alp), omega(om), gewicht(gew)
    {
    }
    
    #include "stdafx.h"
    #include "knoten.h"
    #include <cstdio>
    #include <string>
    #include <sstream>
    
    using namespace std;
    
    knoten::knoten()
    :index(0), name("0")
    {
    }
    
    knoten::knoten(int ind, string nam)
    :index(ind), name(nam)
    {
    }
    
    string knoten::print()
    {
    	ostringstream temp;
        temp << index;
        string zahlenString = temp.str();
    
    	return zahlenString + "; " + name;
    }
    

    bitte um hilfe... weiß wirklich nicht wie es weitergeht



  • Hallo Palme,

    falls Du Informationen aus einer Datei liest, so solltest Du immer die Funktionen des std::istream dafür nutzen. Ein Lesen mit getline und anschließendem Auseinanderfiseln des strings ist keine Lösung. Man versieht dafür jede Klasse/Struktur, die ausgeben und/oder eingelesen wird, mit einem Streamingoperator. Also in Deinem Fall:

    #include <string>
    #include <iosfwd>
    // --   Knoten-Klasse
    class knoten
    {
    public:
        knoten();
        knoten(int ind, const std::string& nam);
    
        friend std::istream& operator>>( std::istream& in, knoten& k );
        friend std::ostream& operator<<( std::ostream& out, const knoten& k ); // ersetzt 'print'
    private:
        int index;
        std::string name;
    };
    // --   Pfeil-Klasse
    class pfeil
    {
    public:
        pfeil();
        pfeil(int alp, int om, int gew);
    
        // --   Pfeil einlesen & ausgeben
        friend std::istream& operator>>( std::istream& in, pfeil& p );
        friend std::ostream& operator<<( std::ostream& out, pfeil& p );
    
    private:
        int alpha;
        int omega;
        int gewicht;
    };
    

    Die Implementierung sähe dann so aus:

    // --   Helferlein zum Überlesen einzelner Zeichen
    template< char C >
    std::istream& Char( std::istream& in )
    {
        char c;
        if( in >> c && c != C )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    
    // --   Knoten-Klasse
    knoten::knoten()
        : index(0), name("0")
    {}
    
    knoten::knoten(int ind, const std::string& nam)
        : index(ind), name(nam)
    {}
    
    // --   Ausgabe (ersetzt: string knoten::print() )
    std::ostream& operator<<( std::ostream& out, const knoten& k )
    {
        return out << k.index << "; " << k.name;
    }
    // --   Einlesen eines Knotens
    std::istream& operator>>( std::istream& in, knoten& k )
    {
        return getline( in >> k.index >> Char<';'> >> std::ws, k.name );
    }
    
    // --  Pfeil
    pfeil::pfeil()
        : alpha(0), omega(0), gewicht(0)
    {}
    
    pfeil::pfeil(int alp, int om, int gew)
        : alpha(alp), omega(om), gewicht(gew)
    {} 
    
    std::istream& operator>>( std::istream& in, pfeil& p )
    {
        return in >> p.alpha >> Char<';'> >> p.omega >> Char<';'> >> p.gewicht;
    }
    std::ostream& operator<<( std::ostream& out, pfeil& p )
    {
        return out << p.alpha << " " << p.omega << " " << p.gewicht;
    }
    

    Da ich gerade an einem Projekt sitze, das nur deshalb dreimal so viel Aufwand erfordert wie es eigentlich erfordern sollte und das alles nur weil der Programmierer globale Variablen verwendet ...

    hier noch mal der ernst gemeinte Hinweis: vermeide globale Variablen!

    palmdale schrieb:

    .. bin ganz neu auf dem gebiet c++ und hab vorher nur mit anderen sprachen zu tu gehabt.

    .. dann solltest Du das auch wissen; das gilt für alle Programmiersprachen.

    Das Öffen der Dateien kannst Du ruhig in das main nehmen, dann sieht es so aus:

    #include <fstream>
    #include <iostream>
    
    void readFromFile( std::istream& fileKnoten, std::istream& filePfeil );
    using namespace std;
    
    int main()
    {
        ifstream inFileKnoten( "knoten.txt" );
        if( !inFileKnoten.is_open() )
        {
            char c;
            cerr << "Fehler: Datei knoten.txt konnte nicht geöffnet werden\n" << endl;
            cin >> c;
            return -1;
        }
    
        ifstream inFilePfeil( "pfeile.txt" );
        if( !inFilePfeil.is_open() )
        {
            char c;
            cerr << "Fehler: Datei pfeile.txt konnte nicht geöffnet werden\n" << endl;
            cin >> c;
            return -1;
        }
    
        readFromFile( inFileKnoten, inFilePfeil ); // Lesen aus den Dateien
    
        getchar();
        return 0;
    }
    

    und dank der Vorarbeit wird jetzt das Lesen ganz einfach:

    void readFromFile( std::istream& fileKnoten, std::istream& filePfeil )
    {
        for( knoten k; fileKnoten >> k; )
        {
            cout << "my knoten: " << k << endl;
        }
        for( pfeil p; filePfeil >> p; )
        {
            cout << "my kanten: " << p << endl;
        }
    }
    

    palmdale schrieb:

    ich komme nicht weiter 😞
    ich kann jetzt meine knoten und kanten erstellen, allerdings weiß ich nicht wie ich diese jetzt sinnvoll in einen container (map???, vektor + linklist???) speichern soll...

    Das kann man erst dann entscheiden, wenn bekannt ist, was Du mit den Knoten und Kanten vor hast. Erst müssen die Anforderungen klar sein, dann kann man sagen, wie das Programm aussehen soll.

    Was ist der Zweck Deines Programms? was soll es tun? was ist der Output?

    Gruß
    Werner



  • wow danke für deine ausführliche antwort, werde mir das zu herzen nehmen und meinen code nochmal überarbeiten. jetzt zu dem graphen.

    im allgemeinen möchte ich erstmal einen container der kanten und knoten speichert. dieser soll dann folgendes ausgeben:

    • Ermittlung des Ausgangsgrades g+(u) und Eingangsgrades g+(u) eines wählbaren
    Knotens
    • Ermittlung der Nachbarn (Vorgänger und Nachfolger) eines wählbaren Knotens

    echt nochmal vielen dank für die tipps... ich such mich bald wund im internet um was gescheites zu finden. werde jetzt mein code nochmal überarbeiten.

    //edit: wenn ich deinen code benutze gibt es einen fehler das der knoten nicht erkannt wird, wenn du den erstellen willst...
    error C2065: 'knoten': nichtdeklarierter Bezeichner (in der readFromFile methode)
    wie verbinde ich denn diese beiden klassen, damit der erkannt wird?

    diese sprache macht mir keinen spaß :(, aber wenigstens gibt es leute die helfen



  • palmdale schrieb:

    • Ermittlung des Ausgangsgrades g+(u) und Eingangsgrades g+(u) eines wählbaren
    Knotens
    • Ermittlung der Nachbarn (Vorgänger und Nachfolger) eines wählbaren Knotens

    Oh - ja dann ist kein Container aus dem C++ Standard wirklich geeignet - schau Dir mal die boost.graph-Librarie an. Die Alternative bestände darin, Dir selbst etwas aus den C++-Containern zusammenzubauen.

    Jeder Knoten enthält dann schon einen Container (vector oder list) mit Zeigern auf seine Nachbarn und dem dazugehörigen Gewicht. Die Knoten selbst könnte man dann in eine std::map abladen, aber wieder nur als Pointer (besser boost.shared_ptr) da sie nicht kopierbar sein dürfen, damit ihre Vorgänger sie sicher wiederfinden.

    palmdale schrieb:

    ich such mich bald wund im internet um was gescheites zu finden. werde jetzt mein code nochmal überarbeiten.

    .. es gibt furchtbar wenig zum Thema IO in C++ - warum auch immer.

    Gruß
    Werner



  • die aufgabe besteht leider darin das ich diese boost.graph-Librarie nicht nehmen kann... 😞

    //edit: hab jetzt deins zum laufen gebracht und beginne zu verstehen was du da machst aufgrund meiner kenntnisse in anderen sprachen.



  • palmdale schrieb:

    //edit: wenn ich deinen code benutze gibt es einen fehler das der knoten nicht erkannt wird, wenn du den erstellen willst...
    error C2065: 'knoten': nichtdeklarierter Bezeichner (in der readFromFile methode)
    wie verbinde ich denn diese beiden klassen, damit der erkannt wird?

    Dann hast Du das #include "knoten.h" dort vergessen.

    palmdale schrieb:

    diese sprache macht mir keinen spaß :(, aber wenigstens gibt es leute die helfen

    .. der Spaß kommt mit der Zeit 😉

    Gruß
    Werner



  • .. der Spaß kommt mit der Zeit 😉

    darauf warte ich jetzt aber schon ne ganze weile, in den anderen (neueren) sprachen hab ich mich sehr schnell zurecht gefunden, aber dieses c++ ist für mich n bisschen wie ein krampf.

    hab deine sachen jetzt zum laufen gebracht und beginne zu verstehen, wie du das aufgebaut hast. vielen vielen dank nochmal dafür (ich hoffe ich halte dich nicht von deinem derzeitigen projekt ab).

    hast du ne idee wie man das löst? ich hatte zuerst an einen vektor gedacht, der eine link liste in sich trägt, eine map zu implementieren hab ich versucht, allerdings bisher ohne erfolg, da ich das mit dem pair nicht verstanden habe...



  • palmdale schrieb:

    .. der Spaß kommt mit der Zeit 😉

    darauf warte ich jetzt aber schon ne ganze weile, in den anderen (neueren) sprachen hab ich mich sehr schnell zurecht gefunden, aber dieses c++ ist für mich n bisschen wie ein krampf.

    Hallo Palme,
    C++ ist eine schwierige Sprache, und sie ist anders.

    palmdale schrieb:

    hab deine sachen jetzt zum laufen gebracht und beginne zu verstehen, wie du das aufgebaut hast. vielen vielen dank nochmal dafür (ich hoffe ich halte dich nicht von deinem derzeitigen projekt ab).

    .. gucke gerade Song Contest - da bin ich geistig nicht ausgelastet. 🕶

    palmdale schrieb:

    hast du ne idee wie man das löst? ich hatte zuerst an einen vektor gedacht, der eine link liste in sich trägt, eine map zu implementieren hab ich versucht, allerdings bisher ohne erfolg, da ich das mit dem pair nicht verstanden habe...

    Ein pair ist einfach eine Struktur mit zwei Membern (first und second) nicht mehr und nicht weniger. Bei einer std::map wird der Member first als Schlüssel benutzt, um das Element (also das ganze pair) zu identifizieren. In second kann dann stehen was will.

    Um den Graph zu realisieren würde ich Dir im Prinzip folgendes vorschlagen. Rüste zunächst Deine knoten-Klasse auf, die wird später Teil des Graphs.

    // --   Knoten-Klasse
    class knoten
    {
    public:
        typedef knoten* KnotenPtr; // evt. typedef boost::shared_ptr< knoten > KnotenPtr;
        struct Next
        {   
            Next( KnotenPtr nachfolger, int gewicht )
                : m_nachfolger( nachfolger ), m_gewicht( gewicht )
            {}
            KnotenPtr m_nachfolger;
            int m_gewicht;
        };
        void Nachfolger( KnotenPtr next, int gewicht );
        int Index() const { return index; }
    // -- usw. wie vorher
    private:
        std::vector< Next > m_nachfolger; // erfordert #include <vector>
    

    Damit bekommt jeder Knoten einen Container in dem alle Nachfolger mit den Gewichten der Kanten stehen.

    In der Methode readFromFile

    typedef std::map< int, knoten::KnotenPtr > Graph;   // erfordert #include <map>
    Graph readFromFile( std::istream& fileKnoten, std::istream& filePfeil );
    

    - Achtung - neuer Returntyp - muss der Graph zusammen gebaut werden:

    Graph readFromFile( std::istream& fileKnoten, std::istream& filePfeil )
    {
        Graph graph;
        // --  erst alle Knoten einlesen, die Liste aller Anchfolger ist jeweils noch leer
        for( knoten k; fileKnoten >> k; )
        {
            graph[ k.Index() ] = new knoten( k );
            cout << "neuer knoten: " << k << endl;
        }
    
        // --  dann die Kanten einlesen und die Knoten verbinden
        for( pfeil p; filePfeil >> p; )
        {
            // erst den Ausgangsknoten suchen
            Graph::iterator alpha = graph.find( p.alpha );
            if( alpha == graph.end() )
            {
                cerr << "Ausgangsknoten-Knoten " << p.alpha << " nicht vorhanden " << endl;
                break;
            }
            // .. dann den Eingangsknoten suchen
            Graph::iterator omega = graph.find( p.omega );
            if( omega == graph.end() )
            {
                cerr << "Eingangs-Knoten " << p.omega << " nicht vorhanden " << endl;
                break;
            }
            alpha->second->Nachfolger( omega->second, p.gewicht );
        }
        return graph;
    }
    

    Achtung -ich habe die Member von 'pfeil' public gemacht, da diese Klasse nur zum Einlesen genutzt wird und es so einfacher wird.

    Bevor ich lange erkläre - frag' einfach was Du nicht verstehst.

    Gruß
    Werner



  • tausend dank ich medietiere darüber und werde jetzt schlafen gehen. morgen werd ich bestimmt dann fragen stellen 😉 wirklich danke für deine zeit.



  • so jetzt ist alles eingebunde, ich bekomme aber leider eine fehlermeldung mit der ich wenig anfangen kann...

    Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall knoten::Nachfolger(class knoten *,int)" (?Nachfolger@knoten@@QAEXPAV1@H@Z)" in Funktion ""class std::map<int,class knoten *,struct std::less<int>,class std::allocator<struct std::pair<int const ,class knoten *> > > __cdecl readFromFile(class std::basic_istream<char,struct std::char_traits<char> > &,class std::basic_istream<char,struct std::char_traits<char> > &)" (?readFromFile@@YA?AV?map@HPAVknoten@@U?map@HPAVknoten@@U?less@H@std@@V?allocator@U?allocator@U?pair@$$CBHPAVknoten@@@std@@@3@@std@@AAV?basic_istream@DU?basic\_istream@DU?char_traits@D@std@@@2@0@Z)"

    ich verstehe auch nicht wo du die neuen methoden wie nachfolger in der knten class implementierst. bisher haste die ja nur in den header geschrieben, richtig?

    hier mal meine header und meine knoten klasse (hab den header in eine extra knoten.h geschrieben):

    knoten.h

    #include "stdafx.h"
    #include <string>
    #include <iosfwd>
    #include <vector>
    
    using namespace std;
    
    // --   Knoten-Klasse
    class knoten
    {
    public:
        knoten();
        knoten(int ind, const string& nam);
    
    	typedef knoten* KnotenPtr;
        struct Next
        {  
            Next( KnotenPtr nachfolger, int gewicht )
                : m_nachfolger( nachfolger ), m_gewicht( gewicht )
            {}
            KnotenPtr m_nachfolger;
            int m_gewicht;
        };
    
        void Nachfolger( KnotenPtr next, int gewicht );
        int Index() const { return index; } 
    
        friend istream& operator>>( istream& in, knoten& k );
        friend ostream& operator<<( ostream& out, const knoten& k );
    private:
        int index;
        string name;
    	std::vector< Next > m_nachfolger;
    };
    

    knoten.cpp

    #include "stdafx.h"
    #include <string>
    #include <iosfwd>
    #include "knoten.h"
    
    using namespace std;
    
    // --   Helferlein zum Überlesen einzelner Zeichen
    template< char C >
    istream& Char( istream& in )
    {
        char c;
        if( in >> c && c != C )
            in.setstate( ios_base::failbit );
        return in;
    }
    
    // --   Knoten-Klasse
    knoten::knoten()
        : index(0), name("0")
    {}
    
    knoten::knoten(int ind, const string& nam)
        : index(ind), name(nam)
    {}
    
    // --   Ausgabe eines Knotens
    ostream& operator<<( ostream& out, const knoten& k )
    {
        return out << k.index << "; " << k.name;
    }
    // --   Einlesen eines Knotens
    istream& operator>>( istream& in, knoten& k )
    {
        return getline( in >> k.index >> Char<';'> >> ws, k.name );
    }
    

    und hier noch der vollständigkeit wegen die main

    // alg_graph.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    #include "stdafx.h"
    #include <fstream>
    #include <iostream>
    #include "knoten.h"
    #include "pfeil.h"
    #include <map>
    
    using namespace std;
    
    typedef std::map< int, knoten::KnotenPtr > Graph;
    Graph readFromFile( std::istream& fileKnoten, std::istream& filePfeil ); 
    
    int main()
    {
        ifstream inFileKnoten( "knoten.txt" );
        if( !inFileKnoten.is_open() )
        {
            char c;
            cerr << "Fehler: Datei knoten.txt konnte nicht geöffnet werden\n" << endl;
            cin >> c;
            return -1;
        }
    
        ifstream inFilePfeil( "pfeile.txt" );
        if( !inFilePfeil.is_open() )
        {
            char c;
            cerr << "Fehler: Datei pfeile.txt konnte nicht geöffnet werden\n" << endl;
            cin >> c;
            return -1;
        }
    
        readFromFile( inFileKnoten, inFilePfeil ); // Lesen aus den Dateien
    
        getchar();
        return 0;
    }
    
    Graph readFromFile( std::istream& fileKnoten, std::istream& filePfeil )
    {
        Graph graph;
        // --  erst alle Knoten einlesen, die Liste aller Anchfolger ist jeweils noch leer
        for( knoten k; fileKnoten >> k; )
        {
            graph[ k.Index() ] = new knoten( k );
            cout << "neuer knoten: " << k << endl;
        }
    
        // --  dann die Kanten einlesen und die Knoten verbinden
        for( pfeil p; filePfeil >> p; )
        {
            // erst den Ausgangsknoten suchen
            Graph::iterator alpha = graph.find( p.alpha );
            if( alpha == graph.end() )
            {
                cerr << "Ausgangsknoten-Knoten " << p.alpha << " nicht vorhanden " << endl;
                break;
            }
            // .. dann den Eingangsknoten suchen
            Graph::iterator omega = graph.find( p.omega );
            if( omega == graph.end() )
            {
                cerr << "Eingangs-Knoten " << p.omega << " nicht vorhanden " << endl;
                break;
            }
            alpha->second->Nachfolger( omega->second, p.gewicht );
        }
        return graph;
    }
    


  • du hast nur vergessen die fkt zu definieren:
    void Nachfolger( KnotenPtr next, int gewicht );

    Und deshalb geht das kompilieren auch fehlerfrei und erst beim Linken am Ende sagt dir der Linker die Fehlermeldung:

    Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall knoten::Nachfolger(class knoten *,int)" (?Nachfolger@knoten@@QAEXPAV1@H@Z)" in Funktion ""class std::map<int,class knoten *,struct std::less<int>,class std::allocator<struct std::pair<int const ,class knoten *> > > __cdecl readFromFile(class std::basic_istream<char,struct std::char_traits<char> > &,class std::basic_istream<char,struct std::char_traits<char> > &)" (?readFromFile@@YA?AV?map@HPAVknoten@@U?map@HPAVknoten@@U?less@H@std@@V?allocator@U?allocator@U?pair@$$CBHPAVknoten@@@std@@@3@@std@@AAV?basic_istream@DU?basic\_istream@DU?char_traits@D@std@@@2@0@Z)"

    Das nicht mehr fette ist nicht mehr ganz so interessant... Da sagt er dir z.Bsp. in welcher Fkt die nicht definierte aufgerufen werden soll - das sieht hier nur bissl extrem unübersichtlich aus, weil er alle typen vollständig hinschreibt...

    bb



  • jup daran lags, super!
    wie kann ich das denn jetzt ausgeben das ich zu einem beliebigen punkt alle kanten bekomme? muss glaub ich nochmal über deinen code schauen, ist ein bischen viel auf einmal...



  • palmdale schrieb:

    Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall knoten::Nachfolger(class knoten *,int)"

    Hallo Palme,

    ich hatte vergessen, Dir die Implementierung dieser Methode zu posten. In Knoten.cpp muss noch eingefügt werden:

    void knoten::Nachfolger( KnotenPtr nachfolger, int gewicht )
    {
        m_nachfolger.push_back( Next( nachfolger, gewicht ) );
    }
    

    D.h. aus dem Nachfolger-Knoten (bzw. dem Pointer auf diesen) und dem Gewicht wird ein Objekt der Struktur 'Next' erzeugt und das wird mit in den vector der Nachfolger aufgenommen (push_back).

    palmdale schrieb:

    wie kann ich das denn jetzt ausgeben das ich zu einem beliebigen punkt alle kanten bekomme? muss glaub ich nochmal über deinen code schauen, ist ein bischen viel auf einmal...

    inden Du z.B. die Ausgabe-Funktion des Knotens aufmotzt. Ein Knoten ist nun mehr als ein Index und der Straßenname. Also in knoten.cpp:

    // --   Ausgabe (ersetzt: string knoten::print() )
    std::ostream& operator<<( std::ostream& out, const knoten& k )
    {
        out << k.index << "; " << k.name;
        if( !k.m_nachfolger.empty() )
            out << "\n"; // Nachfolger in die nächste Zeile schreiben
    
        // Bem.: erfordert #include <algorithm> (copy) und #include <iterator> (ostream_iterator) und Streaming-Operator für Next
        copy( k.m_nachfolger.begin(), k.m_nachfolger.end(), std::ostream_iterator< knoten::Next >( out, ";  " ) );
        return out;
    }
    

    und weil jetzt die Ausgabe von knoten::Next benötigt wird, auch in knoten.cpp

    // --   Streaming-Operator für Next
    std::ostream& operator<<( std::ostream& out, const knoten::Next& kante )
    {
        return out << "(" << kante.m_gewicht << ")-> " << kante.m_nachfolger->Index();
    }
    

    und im Header (knoten.h) noch die Deklaration des Streamingoperators

    struct Next
        {   
            Next( KnotenPtr nachfolger, int gewicht )
                : m_nachfolger( nachfolger ), m_gewicht( gewicht )
            {}
            friend std::ostream& operator<<( std::ostream& out, const knoten::Next& kante );
        // usw. ...
    

    So kannst Du auch den Graphen nach dem Einlesen wieder ausgeben - im main() zu ändern:

    Graph graph = readFromFile( inFileKnoten, inFilePfeil ); // Lesen aus den Dateien
        for( Graph::iterator i = graph.begin(); i != graph.end(); ++i )
        {
            cout << *(i->second) << endl;
        }
    

    .. was dann noch fehlt ist das Aufräumen im Speicher! Kannst Du boost.shared_ptr benutzen?

    Gruß
    Werner



  • eigentlich nur native c++, d.h. so viel wie möglich selber beasteln 😉



  • Du kannst natürlich auch einen shared_ptr selber basteln. 😉

    Vielleicht nicht mit der Komplexität wie bei Boost, aber die wichtigen Dinge wie Referenzzählung sollten nicht allzu schwer zu implementieren sein.



  • hier kann geschlossen werden, vielen dank allen, die mir geholfen haben... konnte mein projekt dadurch erfolgreich abschliessen... (besonderen dank an werner für die geopferte zeit (auch während des grand prix ;)))


Anmelden zum Antworten