Anzeige:
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 18

Thema: Iterator als Eigenschaft, ok?

  1. #1
    Registrierter Benutzer
    Registriert seit
    20.11.2004
    Beiträge
    122

    Iterator als Eigenschaft, ok?

    Hallo Forum.
    Ich habe ein Problem.

    Erstmal kurz zur Vorgeschichte:
    Ich mache ein Programm zur Verwaltung von Decks fuer ein Kartenspiel.
    Jede Karte hat einen Typ, z.B. "Human Wizard", "Lobotemist", usw.

    Ich will den String nicht direkt als Eigenschaft mit in die "Card"-Klasse tun.
    Deswegen habe ich jetzt zwei Klassen, "Card" und "CardTypeList",
    in der sich jeder Kartentyp des Spiels einmal in einer Liste befindet.

    Ich habe mir ueberlegt in der "CardTypeList"-Klasse ein Set zu
    implementieren, zu der ich dann Kartentypen hinzufuegen kann und in der
    "Card"-Klasse ist dann ein Iterator als Eigenschaft fuer den Typ der Karte,
    der dann auf den entsprechen Typ in der Typ-Liste zeigt.

    Macht man das so?
    Wenn nein, wie macht mans sonst?

    Danke & Gruß
    Kai
    Geändert von `kk (25-10-2005 um 17:22 Uhr)

  2. #2
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    Das Problem mit Iteratoren ist halt dass (zumindest bei den STL-Iteratoren) wann immer du an der Liste wo du den Iterator her hast was änderst, der Iterator nicht mehr gültig ist.
    D.h. das Ding ist für deine Zwecke soweit ich das verstanden habe nicht wirklich brauchbar.

    Was genau ist der Grund wieso du den String nicht als Member in dem Objekt speicherst?

    MfG Peschmä
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

  3. #3
    Registrierter Benutzer
    Registriert seit
    20.11.2004
    Beiträge
    122
    Hi peschmae, danke fuer deine Antwort.

    Hm.. ich wuerde den Iterator const machen,
    dann duerfte es das angesprochene Problem nicht geben.

    Ich hab zwei Gruende warum ich keinen std::string nehmen moechte:
    1) Es sind ueber 12.000 Karten, d.h. 12.000 mal einen langen String in jedem Karten-Objekt
    2) Datenredundanz
    3) Ich finde es unuebersichtlich

    Hat jemand denn nochn anderen Vorschlag?
    Ich muss ja keinen Iterator nehmen, mir faellt nur
    momentan nichts Anderes ein...

    Gruß
    Kai
    Geändert von `kk (25-10-2005 um 18:00 Uhr)

  4. #4
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Das hört sich nach einem Fall für einen shared pointer an, zum Beispiel shared_ptr<> aus der Boost lib.

    Oder ein selbst implementiertes Handle

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  5. #5
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Hm.. ich wuerde den Iterator const machen,
    dann duerfte es das angesprochene Problem nicht geben.
    Ob der Iterator "const" ist, hat nichts damit zu tun, ob er gültig ist. Bei welchen Operationen auf dem entsprechenden Container er gültig bleicht, liest du am besten in einer Referenz nach.

    Wenn du einen Iterator zum Zeigen auf das Element im Container wegen dieser Problematik nicht gut verwenden kannst, dann könnte vielleicht ein Index in den Container an Stelle eines Iterators gehen. Z.b. ein Integer als Index in einen std::vector. Oder du verwendest eine Map.

  6. #6
    Registrierter Benutzer
    Registriert seit
    20.11.2004
    Beiträge
    122
    Hi locus.
    Das ist lustig..., denn genau so habe ich es schon probiert.
    Dann war der erste Gedanke wie immer der Richtige...

    Edit:
    So... nach mehr oder weniger kleinen Schwierigkeiten funktioniert es nun wunderbar:
    Code:
    std::pair< int, bool >
    CardTypeList::add( const std::string& type )
    {
        if ( m_typelist.insert( std::make_pair( type, m_typelist.size() ) ).second )
            return std::make_pair( m_typelist.size()-1, true );
    
        m_iter = m_typelist.find( type );
        return std::make_pair( (*m_iter).second, false );
    }
    Danke fuer den Schubser.

    Gruß
    Kai
    Geändert von `kk (25-10-2005 um 22:31 Uhr)

  7. #7
    Registrierter Benutzer
    Registriert seit
    20.11.2004
    Beiträge
    122
    So.. ich nochmal.
    Die Methode da oben funktioniert natuerlich hervorragend..
    nur komm ich jetzt nicht mehr ueber den Index an den Typ, den ich brauche.
    Dafuer muesste es "int, string" heißen... zum Suchen brauche ich aber "string, int".

    Ist irgendwie ne Zwickmuehle...
    Kennt da jemand den Ausweg?

    Ich brauechte irgendein Container mit zwei Schluesseln. :/

    Danke & Gruß
    Kai
    Geändert von `kk (26-10-2005 um 16:27 Uhr)

  8. #8
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Irgendwie ist mir der Sinn deines Codeschnippsels auch nicht so klar. "m_typelist" ist eine Map, oder? Aber warum fügst du da Elemente ein, welche die Größe der Map enthalten? Ich dachte eigentlich, dass es gehen müsste, wenn du in deiner Karten-Klasse einen Index bzw. Schlüssel speicherst, und damit dann aus einer Map den entsprechenden Kartentyp herausholst (der, wenn ich dich richtig verstanden habe, als String gespeichert wird).

    Ich brauechte irgendein Container mit zwei Schluesseln.
    Boost hat einen solchen. Heißt "Multi Index Container".

  9. #9
    Registrierter Benutzer
    Registriert seit
    20.11.2004
    Beiträge
    122
    Zitat Zitat von locus vivendi
    Irgendwie ist mir der Sinn deines Codeschnippsels auch nicht so klar. "m_typelist" ist eine Map, oder?
    Ja...
    Ich habe ne Map genommen, weil ich nicht weiß
    wie ich bei der Benutzung eines Vectors nach dem
    Suchen durch den Iterator auf den Index komme.

    Ich drueck mich manchmal etwas kompliziert aus,
    hier lieber etwas Quellcode:

    Code:
    ...
        std::vector< std::string > vec;
        std::vector< std::string >::iterator iter;
    
        vec.push_back( "typ1" );
        vec.push_back( "typ2" );
        vec.push_back( "typ3" );
    
        iter = find( vec.begin(), vec.end(), "typ2" );
        
        /*
        Hier muesste ich jetzt die aktuelle Position im Vector
        zurueckgeben. Aber wie komme ich vom Iterator
        auf den Index?
    
        Ich koennte ganz simpel die Liste durchlaufen,
        dann haette ich den Index. Aber ich dachte das geht
        evtl. etwas eleganter (und vor allem schneller...):
        */
    
        for (int i = 0; i < vec.size(); ++i) {
            if ( vec[i] == type ) // Der typ, der eingefuegt werden soll
                return i;
    
            vec.push_back( type );
            return vec.size();
        }
    
        return 0;
    ...
    Danke fuer Hilfe.

    Gruß
    Kai
    Geändert von `kk (26-10-2005 um 17:21 Uhr)

  10. #10
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Ja. Map statt vector, weil ich nicht weiß wie ich ueber den
    Iterator die aktuelle Position im Vector zurueckgeben kann.
    Das geht (z. B.) mit std::distance (also z.B. "distance(der_vector.begin(), anderer_iterator)")

    Vermutlich verstehe ich da wieder irgend etwas falsch, aber mir ist nicht so ganz klar, weshalb du zusätzlich zum Schlüssel der Map noch einen Index brauchst. Die Map hatte ich ja gerade deshalb vorgeschlagen, weil man damit *anstelle* eines (numerischen) Indexes einen (fast) beliebigen Typ als Schlüssel benutzen kann. Ein Schlüssel ist ja nichts anderes als ein verallgemeinerter Index.

  11. #11
    Registrierter Benutzer
    Registriert seit
    20.11.2004
    Beiträge
    122
    Na eben deshalb, weil ich nicht wusste wie ich
    ueber den Iterator an den Index komme!
    Also dachte ich mir, ich erstelle einfach ne Map mit dem String +
    dem Index damit ich die Position zurueckgeben kann.

    Aber dank deinem Tipp kann ich das jetzt nochmal
    ausprobieren. Mit std::find gehts bestimmt viel schneller
    als immer den ganzen Vector zu durchlaufen.

    Danke auf jeden Fall schonmal..
    Ich meld mich.

    Gruß
    Kai

    Edit: Hi nochmal..., bist du dir sicher das es distance heißt? Ich finde das weder in irgendeinem Buch noch ueber google.
    Geändert von `kk (26-10-2005 um 17:48 Uhr)

  12. #12
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Zitat Zitat von peschmae
    Das Problem mit Iteratoren ist halt dass (zumindest bei den STL-Iteratoren) wann immer du an der Liste wo du den Iterator her hast was änderst, der Iterator nicht mehr gültig ist.
    Das stimmt so nicht! Es hängt immer von dem Container ab. Beispiel list:
    Zitat Zitat von SGIs STL Seite zu list
    Lists have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed.

  13. #13
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Na eben deshalb, weil ich nicht wusste wie ich
    ueber den Iterator an den Index komme!
    Also dachte ich mir, ich erstelle einfach ne Map mit dem String +
    dem Index damit ich die Position zurueckgeben kann
    Okay, jetzt habe ich es verstanden.

    Edit: Hi nochmal..., bist du dir sicher das es distance heißt? Ich finde das weder in irgendeinem Buch noch ueber google.
    Ja. std::distance aus dem Header <iterator>. Das müsste in jeder guten Referenz zu finden sein. Z.b. in der von Dinkumware. Aber bei einem Vector musst du auch nicht distance nehmen. Dessen Iteratoren unterstützen eine "-"-Operation, die ebenfalls den Abstand zwischen zwei Iteratoren berechnet.

  14. #14
    Registrierter Benutzer
    Registriert seit
    20.11.2004
    Beiträge
    122
    Hi locus.
    Dank dir, es funktioniert nun super...
    genau so wollte ich das haben.

    Fuer alle, die interessiert sind wie es nun aussieht:
    Code:
    std::pair< int, bool >
    CardTypeList::add( const std::string& type )
    {
        std::vector< std::string >::iterator found;
        found = find( m_typelist.begin(), m_typelist.end(), type );
    
        if ( found != m_typelist.end() ) {
            int index = m_typelist.begin() - found;
            return std::make_pair( index, false );
        }
    
        m_typelist.push_back( type );
        return std::make_pair( m_typelist.size(), true );
    }
    Gruß
    Kai

  15. #15
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Vorsicht!
    Code:
    int index = m_typelist.begin() - found;
    Das ist zwar erlaubt, aber du musst dir im klaren darüber sein, dass "index" nun nicht positiv ist.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •