Datei einlesen und Daten in Unordered Map speichern



  • Hallo C++ Forum,

    dies ist mein erster Beitrag und ich hoffe, ihr könnt mir bei meinem Problem weiterhelfen. Erstmal jedoch ein Hallo an alle 😃

    Zum Problem:
    Ich habe eine Textdatei mit Zahlenwerten, die durch ein Komma getrennt sind. Nun möchte ich diese Zahlen einzeln einlesen und in eine Unordered Map abspeichern, also zB. Zahl1 -> "Erste Zahl" , Zahl2 -> "Zweite Zahl" usw, wobei das in Anführungszeichen für den key steht, womit ich auf die Elemente in der Map zugreifen kann. Hier mein Code, der natürlich nicht das tut, was er soll:

    #include "karte.hpp"
    #include <iostream>
    #include <unordered_map>
    #include <fstream>
    #include <sstream>
    
    using namespace std;
    
    int main()
    {
    	string line;
    	ifstream kartenDaten ("Karten/Karten.csv");
    
    	typedef tr1::unordered_map< string, int > hashmap;
        hashmap faehigkeiten;
    	stringstream stringToInt;
    
    	if (kartenDaten.is_open())
    	{
    		int y = 1;
    
    		while( !kartenDaten.eof())
    		{
    			getline (kartenDaten, line, ',');
    			cout << "Durchgang" << y << ": " << line << endl;
    
    			stringToInt << line;
    			cout << "Durchgang" << y << ": " << stringToInt << endl;
    
                            switch(y)
    			{
    				case 1: stringToInt >>   faehigkeiten["karteZiehen"];
    						break;
    				case 2: stringToInt >> faehigkeiten["aktionenPlus"];
    						break;
    			}
    
    			y++;
    		}
    		kartenDaten.close();
    	}else
    	{
    		cout << "Datei kann nicht gefunden werden!" << endl;
    		return -1;
    	}
    
    	stringToInt >> faehigkeiten["karteZiehen"];
    
    	cout << faehigkeiten["karteZiehen"] << endl;
    	system("PAUSE");
    
    }
    

    Bitte lacht nicht über den bestimmt ziemlich schlechten Code, aber ich lerne doch noch 😉 Problem ist, dass die case Anweisung die erste Zahl richtig einliest und abspeichert, jedoch die Nächste nicht. Könnt ihr mir da Tipps und Tricks geben?
    Achja, die couts sind nur zu Testzwecken da, also nicht wundern xD

    Grüße,
    Neras



  • Hallo Neras,

    willkommen im Forum!

    Zu Deinem Code: Du solltest die integer Werte direkt aus der Datei lesen, statt den Umweg über den stringstream zu nehmen. Das Komma kannst Du mit einem kleinen Helferlein überlesen (komma s.u.). Deine Schleife (ab Zeile 20 bis 38) könnte dann so aussehen

    int f;
            for( int y = 1; kartenDaten >> f >> komma; ++y )
            {
                switch(y)
                {
                case 1: faehigkeiten["karteZiehen"] = f;
                    break;
                case 2: faehigkeiten["aktionenPlus"] = f;
                    break;
                }
            }
    

    Der Manipulator komma wird vor dem main definiert

    std::istream& komma( std::istream& in )
    {
        char k;
        if( in >> k && k != ',' )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    

    Der Rest ist entsprechend zu ändern.
    Einen Thread mit ähnlichem Thema findest Du auch hier.

    Gruß
    Werner



  • Hallo Werner Salomon,

    vielen Dank für die schnelle Antwort. Klappt alles wunderbar. Den anderen Thread werde ich mir mal durchlesen; da stehen bestimmt viele Tipps drin, die ich mir merken kann 😃

    Grüße,
    Neras

    EDIT:
    Hab leider wieder ein Problem. Nachdem ich die Methoden aus der main in eine andere cpp. Datei gepackt habe, wirft mit der Compiler folgenden Fehler aus:

    error C2679: Binärer Operator '>>': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operanden vom Typ 'overloaded-function' akzeptiert 
    (oder keine geeignete Konvertierung möglich)
    

    und zwar an dieser Stelle:

    for( int y = 1; kartenDaten >> f >> komma; ++y )
    

    Kann mir da einer weiterhelfen ^^°



  • Hast du da ebenfalls die includes drin?

    Jede Übersetzungseinheit braucht alle Definitionen von neuem.



  • Also ich hab den Code in eine cpp Datei und eine Header Datei getrennt.
    Im Header stehen folgende includes:

    #include <unordered_map>
    #include <fstream>
    #include <iostream>
    

    Und die in der cpp:

    #include "kartenfabrik.hpp"
    using namespace std;
    

    Wobei halt der Header "kartenfabrik.hpp" heißt.

    Grüße,
    Neras



  • Probiers mal noch mit dem:

    #include <istream>
    


  • Fuktioniert leider nicht mit dem neuen Include. Ich poste mal meinen Quellcode, hilft vll. weiter 😉

    Header:

    #include "karte.hpp"
    #include <unordered_map>
    #include <fstream>
    #include <iostream>
    #include <istream>
    
    class Kartenfabrik
    {
    		//Attribute
    
    		//Methodendefinition
    	public:
    		Kartenfabrik();
    
    		void karteErstellen();
    		void stapelErstellen();
    
    		std::istream& komma( std::istream& in );
    
    };
    

    CPP:

    #include "kartenfabrik.hpp"
    using namespace std;
    
    			/* Methodenimplementierung */
    Kartenfabrik::Kartenfabrik()
    {
    
    } 
    
    void Kartenfabrik::karteErstellen()
    {
    	ifstream kartenDaten ("Karten/Karten.csv");
    
    	typedef tr1::unordered_map< string, int > hashmap;
        hashmap faehigkeiten;
    
    	if (kartenDaten.is_open())
    	{
    		int f;
            for( int y = 1; kartenDaten >> f >> komma; ++y )
            {
                switch(y)
                {
                case 1: faehigkeiten["karteZiehen"] = f;
    					break;
                case 2: faehigkeiten["aktionenPlus"] = f;
    					break;
    			case 3: faehigkeiten["kaufenPlus"] = f;
    					break;
    			case 4: faehigkeiten["goldPlus"] = f;
    					break;
    			case 5: faehigkeiten["gegnerKartenAblegen"] = f;
    					break;
    			}
            }
    		kartenDaten.close();
    	}else
    	{
    		cout << "Datei kann nicht gefunden werden!" << endl;
    
    	}
    
    	cout << faehigkeiten["karteZiehen"] << endl;
    	cout << faehigkeiten["aktionenPlus"] << endl;
    }
    
    void Kartenfabrik::stapelErstellen()
    {
    
    }
    
    istream& Kartenfabrik::komma( istream& in )
    {
        char k;
        if( in >> k && k != ',' )
            in.setstate( ios_base::failbit );
        return in;
    }
    

    Grüße,
    Neras



  • class Kartenfabrik
    {
            //Attribute
    
            //Methodendefinition
        public:
            Kartenfabrik();
    
            void karteErstellen();
            void stapelErstellen();
    
    };
    
    std::istream& komma( std::istream& in );
    
    istream& komma( istream& in )
    {
        char k;
        if( in >> k && k != ',' )
            in.setstate( ios_base::failbit );
        return in;
    }
    


  • Das scheint fuktioniert zu haben. Danke für deine Hilfe 😃
    Kannst du mir bitte aber noch sagen, wieso ich diesen Teil des Codes außerhalb der Klasse lassen musste?

    Grüße,
    Neras



  • Neras schrieb:

    Das scheint fuktioniert zu haben. Danke für deine Hilfe 😃
    Kannst du mir bitte aber noch sagen, wieso ich diesen Teil des Codes außerhalb der Klasse lassen musste?

    Grüße,
    Neras

    Weil es sonst beim lookup nicht gefunden wird.



  • Sorry, wenn ich das jetzt frage, aber was ist ein "lookup"? Ich hab gegooglet (vielleicht nicht ausreichend, aber schon eine Weile) aber nichts aussagekräftiges gefunden. ^^°

    Grüße,
    Neras



  • Neras schrieb:

    Sorry, wenn ich das jetzt frage, aber was ist ein "lookup"?

    Ich würde es mit "Nachschlagen" übersetzen.



  • Neras schrieb:

    Sorry, wenn ich das jetzt frage, aber was ist ein "lookup"? Ich hab gegooglet (vielleicht nicht ausreichend, aber schon eine Weile) aber nichts aussagekräftiges gefunden. ^^°

    Grüße,
    Neras

    Der Compiler sucht da eine Funktion, die implizit ein std::istream erwartet, du hast da allerdings eine Funktion, die implizit einen Zeiger auf ein Objekt (hier Kartenfabrik) und dann erst einen std::istream erwartet. Wenn du da Membervariablen hast, die du ausgeben möchtest, dann kannst du die Funktion auch friend machen. Dann klappt das auch.

    Und der lookup ist genau das suchen nach passenden Funktionen.


Anmelden zum Antworten