auswertung von Txt



  • Hallo,
    ich muss eine Txt folgender Form auswerten:

    K 10 os
    7 Q s pot
    usw.

    Als erstes stehen die zwei Karten da. Als nächstes die Farben (s = Gleiche
    Farbe; os = Ungleiche Farbe) und als letztes kann noch pot da stehen, falls
    jemand bei dieser Hand den Pot gewonnen hat.

    Ich muss jetzt in einer Tabelle die Anzahl der Hände auflisten (s und os sind
    unterschiedliche Hände) und dazu noch zu jeder Hand die Anzahl der Pöte).

    Ich weiß jetzt nicht wie ich das in einer Tabelle unterbringen soll. Ich hab
    es mir wie folgt vorgestellt:

    Hand | Anzahl | Anzahl Pöte
         | s   os | s        os
    A A  | 0    2 | 0         1
    usw.
    

    (Ich habe es in Codeklammern gefasst, damit der Einzug bleibt)

    Also eine zweidimensionale Tabelle. Aber wie soll ich von Hand zum Index in der
    Tabelle kommen? Außerdem ist es hirnlos in der Tabelle K 10 und 10 K zu haben.
    Also immer nur eine Version.

    Danke im Voraus!



  • 😞



  • Hi D,

    Ich würd das alles in ne map packen (Paar von Hand und Statitik) und die Daten
    dann pro eingelesene Zeile aktualisieren.

    Ich dachte da an sowas:

    #include <map>
    #include <iostream>
    
    class Statistic{
    
    private:
    	unsigned int wonHand;
    
    public:
    	Statistic() : wonHand(0){
    	}
    
    	void increaseWonHand(){
    		++wonHand;
    	}
    
    	unsigned int countWonHand(){
    		return wonHand;
    	}
    };
    
    class Hand{
    	typedef unsigned int CardValue;
    
    	CardValue value1;
    	CardValue value2;
    	bool suited;
    
    public:
    	Hand(Hand::CardValue v1, Hand::CardValue v2, bool suited): value1(v1), value2(v2), suited(suited){
    		if(v2>v1){
    			std::swap(value1, value2);
    		}
    	}
    
    	char getAbbreviation(CardValue v) const{
    		switch(v){
    			case 8:
    				return 'T';
    			case 9:
    				return 'J';
    			case 10:
    				return 'Q';
    			case 11:
    				return 'K';
    			case 12:
    				return 'A';
    			default:
    				return (char)('2'+v);
    		}
    	}
    
    	void printHand(std::ostream& s) const {
    		s << getAbbreviation(value1) << getAbbreviation(value2);
    		if(suited)
    			s << 's';
    		else
    			s << 'o';
    	}
    
    	bool operator<(const Hand& h) const { 
            if(this->value1 < h.value1)
    			return true;
    		else{
    			if(this->value1 == h.value1){
    				if(this->value2 < h.value2)
    					return true;
    				else if(this->value2 == h.value2){
    					return !this->suited && h.suited;
    				}
    			}
    		}
    		return false;
    	}
    
    };
    
    std::ostream& operator <<(std::ostream& s, const Hand& card){
    	card.printHand(s);
    	return s;
    }
    
    int main(){
    	std::map<Hand, Statistic> map;
    	for(unsigned int i=0; i<13; ++i){
    		for(unsigned int j=i; j<13; ++j){
    			map.insert(std::make_pair(Hand(i,j, false),Statistic()));
    			if(i!=j){
    				map.insert(std::make_pair(Hand(i,j, true),Statistic()));
    			}
    		}		
    	}
    	Statistic& statistic = map[Hand(12,11, false)];
    	statistic.increaseWonHand();
    	statistic = map[Hand(11,12, false)];
    	statistic.increaseWonHand();
    	for(std::map<Hand, Statistic>::iterator it= map.begin(); it != map.end(); ++it){
    		std::cout << (*it).first << ": " << (*it).second.countWonHand() << std::endl;
    	}
    	return 0;
    }
    

    Natürlich mußt du die Ausgabe an die Tabelle anpassen. Wenn du Probleme beim
    einlesen der Daten aus der Datei hast, kannste dich ja nochmal melden.
    Irgendwer hilft bestimmt.

    Gruß,
    CSpille



  • Hallo D,

    das Hauptproblem dürfte das Einlesen sein. Besonders schwierig ist es hier deshalb, weil der Test 'pot' einmal da sein kann und einmal nicht. Ich unterstelle mal, dass hinter einer 'Hand' immer ein Zeilenumbruch kommt. Das ganze ist ein etwas ungünstiges Format.
    Standard-Vorgehen .. wie immer braucht man zunächst eine Sruktur/Klasse, die man liest und diese wird dann mit dem Streaming-operator ausgestattet:

    void trim( std::string& str ) // besser: boost::trim
    {
        while( !str.empty() && isspace( str[0] ) )
            str.erase( str.begin() );
        for( std::string::iterator i; !str.empty() && isspace( *(i = str.end()-1) ); )
            str.erase( i );
    }
    class Hand
    {
    public:
        enum pot_type { kein_pot, pot };
        enum farben_type { os, s };
    
        // -- diese Funktion liest eine 'Hand'
        //    Format: <Karte> <Karte> {s|os} [pot] LF
        friend std::istream& operator>>( std::istream& in, Hand& hnd )
        {
            // --   die beiden Karten
            if( !(in >> hnd.m_karten.first >> hnd.m_karten.second) )
                return in;
            if( hnd.m_karten.second > hnd.m_karten.first )
                swap( hnd.m_karten.first, hnd.m_karten.second );
    
            // --   gleiche oder ungleiche Farbe
            std::string f;
            if( in >> f && f != "s" && f != "os" )
                in.setstate( std::ios_base::failbit );  // muss 's' oder 'os' sein
            if( !in )
                return in;
            hnd.m_farbengleich = (f == "s"? Hand::s: Hand::os);
    
            // --   optional 'pot' bis Zeilenende
            std::string txt;
            if( getline( in, txt ) )
            {
                trim( txt );
                if( !txt.empty() && txt != "pot")
                    in.setstate( std::ios_base::failbit );  // muss 'pot' oder nichts sein
            }
            if( !in )
                return in;
            hnd.m_pot = (txt == "pot"? Hand::pot: Hand::kein_pot);
    
            return in;
        }
    
        // --   ein paar Getters
        std::pair< std::string, std::string > kartenpaar() const
        {
            return m_karten;
        }
        bool ist_s() const { return m_farbengleich == Hand::s; }
        bool hat_pot() const { return m_pot == Hand::pot; }
    
    private:
        std::pair< std::string, std::string > m_karten;
        farben_type m_farbengleich;
        pot_type m_pot;
    };
    

    Damit kann man die Datei schon mal lesen. Die Tabelle für die Ausgabe ist als map gut zu realisieren. Aber erstmal braucht man dazu die Zeile einer Tabelle - also

    class Line
    {
    public:
        Line()
            : m_anz_s( 0 )
            , m_anz_os( 0 )
            , m_anz_poete_s( 0 )
            , m_anz_poete_os( 0 )
        {}
    
        int m_anz_s;
        int m_anz_os;
        int m_anz_poete_s;
        int m_anz_poete_os;
    };
    

    Wichtig: der Defaultkonstruktor setzt die Member auf 0 - so braucht man sich um das Anlegen nicht vorhandener map-Elemente nicht mehr zu kümmern.

    Damit ausgerüstet wir es ab jetzt übersichtlich:

    #include <algorithm> // swap
    #include <fstream>
    #include <iomanip> // setw
    #include <iostream>
    #include <map>
    #include <string>
    
    class Hand; // (s.o)
    class Line; // (s.o)
    
    int main()
    {
        using namespace std;
        typedef map< std::pair< std::string, std::string >, Line > Tabelle;
        Tabelle tabelle;
        ifstream datei("input.txt");
        for( Hand hand; datei >> hand;  )  // Hände aus Datei lesen bis zum Datei-Ende
        {
            // Informationen aus einer Hand in die passende Zeile ablegen
            Line& line = tabelle[ hand.kartenpaar() ];
            if( hand.ist_s() )
            {
                ++line.m_anz_s;
                if( hand.hat_pot() )
                    ++line.m_anz_poete_s;
            }
            else // Hand ist os
            {
                ++line.m_anz_os;
                if( hand.hat_pot() )
                    ++line.m_anz_poete_os;
            }
        }
    
        // --  ab hier erfolgt die Ausgabe ...
        // Tabellenkopf ausgeben
        cout << "Hand  | Anzahl | Anzahl Pöte" << endl;
        cout << "      | s   os | s        os" << endl;
        // Tabelle ausgeben
        for( Tabelle::iterator i = tabelle.begin(); i != tabelle.end(); ++i )
        {
            cout << setw(2) << i->first.first << " " << setw(2) << i->first.second << " | "
                << setw(2) << i->second.m_anz_s << " " << setw(3) << i->second.m_anz_os << " | "
                << setw(2) << i->second.m_anz_poete_s << " " << setw(8) << i->second.m_anz_poete_os 
                << endl;
        }
        return 0;
    }
    

    .. schreibt man Pot nicht mit zwei 't'?

    Gruß
    Werner


Anmelden zum Antworten