std::map verliert Einträge



  • ZuK schrieb:

    hehej schrieb:

    Diese verliert nämlich fast ihr Wissen über ihre Einträge.

    Lass mich raten: Fast heist du hast nur eine einzigen Eintrag in deiner Map.
    Kurt

    Nein, lasse ich die Map nach der Schleife durch die Iteratoren ausgeben, dann hat die Datei genau so viele Zeilen wie ich Datensätze in der Tabelle habe.
    Die Daten sind schon drin...



  • Mir fällt grad auf, dass deine Komparatorfunktion baurecht_key_cmp keine Ordnungsrelation (strict weak ordering) erzeugt. Die Vergleichsfunktion sollte ein "kleiner-als" Operator sein.
    Ich hab mir zwar nicht alles durchgelesen, aber sowas könnte schon dazu führen, dass die map nicht ganz das tut, was man erwartet.



  • hehejo schrieb:

    Nein, lasse ich die Map nach der Schleife durch die Iteratoren ausgeben, dann hat die Datei genau so viele Zeilen wie ich Datensätze in der Tabelle habe.
    Die Daten sind schon drin...

    Was geht denn dann verloren ?

    Bashar schrieb:

    Mir fällt grad auf, dass deine Komparatorfunktion baurecht_key_cmp keine Ordnungsrelation (strict weak ordering) erzeugt. Die Vergleichsfunktion sollte ein "kleiner-als" Operator sein.
    Ich hab mir zwar nicht alles durchgelesen, aber sowas könnte schon dazu führen, dass die map nicht ganz das tut, was man erwartet.

    So änlich war auch meine Vermutung.
    Kurt



  • Bashar schrieb:

    Mir fällt grad auf, dass deine Komparatorfunktion baurecht_key_cmp keine Ordnungsrelation (strict weak ordering) erzeugt. Die Vergleichsfunktion sollte ein "kleiner-als" Operator sein.
    Ich hab mir zwar nicht alles durchgelesen, aber sowas könnte schon dazu führen, dass die map nicht ganz das tut, was man erwartet.

    Ok, das wusste ich nicht, ich hab das so woanders gesehen.
    Mal sehen wie ich das ummünzen kann. So richtig:

    struct baurecht_key_cmp {
      operator <(const baurecht_key & lhs, const baurecht_key & lhs) {
        if(lhs.BetrNr < rhs.BetrNr && lhs.AnwKz < rhs.AnwKz && lhs.UserName < rhs.UserName)
          return true;
        return false;
      }
    };
    

    ZuK schrieb:

    Was geht denn dann verloren ?

    Z.B. wird der Eintrag [999999 EK BRZ][1] nicht mehr gefunden, obwohl ich ihn in der Schleife hinzufüge.
    In meiner (inzwischen entfernten Rekursion) suche ich nach jedem Eintrag und füge den dann hinzu falls es ihn nicht gibt.
    Lasse ich mir nach der Rekursion die Map ausgeben, dann wird's schauerlich:
    Es gibt jeden Key zweimal: Alle alten Werte und alle neu hinzugefügten Werte.

    Also ist wohl baurecht_key_cmp das Böse?!



  • hehejo schrieb:

    Also ist wohl baurecht_key_cmp das Böse?!

    Das dürfte dein fehler sein. Aber deine neu funktion baurecht_key_cmp ist sicher auch nicht viel besser denn du gibst nur dann < zurück wenn alle felder < sind.
    Ich würde mir einen einfacheren Key für die Map einfallen lassen.
    K.



  • hehejo schrieb:

    Mal sehen wie ich das ummünzen kann. So richtig:

    struct baurecht_key_cmp {
      operator <(const baurecht_key & lhs, const baurecht_key & lhs) {
        if(lhs.BetrNr < rhs.BetrNr && lhs.AnwKz < rhs.AnwKz && lhs.UserName < rhs.UserName)
          return true;
        return false;
      }
    };
    

    Nein, erstens, warum operator<? operator() war schon ganz gut. Das dürfte der Compiler gar nicht durchgehen lassen.
    Zweitens funktioniert das so nicht im Sinne einer Ordnungsrelation. Wenn a<b == false ist und b>a==false ist, dann gelten die Elemente als gleich. Das passiert bei dir schon, wenn eine der drei Bedingungen falsch ist, nicht erst, wenn alle drei Elemente gleich sind.

    Du solltest so vorgehen: Zuerst ein Element prüfen, wenn < oder >, sofort true bzw. false zurückgeben, bei Gleichheit das nächste Element in der gleichen Weise prüfen. So wie man auch zwei Strings vergleicht.



  • Du solltest dir evtl. mal anschauen, welcher Art baurecht_key_cmp sein sollte.
    Z.B. ist der default-comparator bei Maps less<key>.
    Es gibt (ich glaube in <algorithm>) ein Funktionsobjekts-Template

    template <class T>
    struct less : public binary_function<T,T,bool>
      bool operator()(const T& x, const T& y) const;
    

    Dieses Funktinsobjekt beruht auf der existenz eines operator< für die KLasse T

    Du kannst also entweder einen operator< für baurecht_key definieren und bei der map Comp auf default lassen, oder du definierst ein Funktionsobjekt(also eines dass den operator() definiert), das eine Ordnungsrelation definiert. Das gute Stück sollte dann von binary_function<baurecht_key, baurecht_key, bool> abgeleitet sein:

    struct baurecht_key_comp 
      : public binary_function<baurecht_key, baurecht_key, bool>
      bool operator()(const baurecht_key& x, const baurecht_key& y) const
        {
        //eine ordentliche Implementation, die auch Gleichheit
        //der einzelnen Komponenten berücksichtigt
        };
    


  • struct baurecht_key {
      string BetrNr;
      string AnwKz;
      string UserName;
      bool operator <(const baurecht_key& rhs) {
        if(BetrNr < rhs.BetrNr)
          return true;
        else if(AnwKz < rhs.AnwKz)
        // oder so: else if(BetrNr >= rhs.BetrNr && AnwKz < rhs.AnwKz)
          return true;
        else if(UserName < rhs.UserName)
          return true;
    
        return false;
      }
    };
    

    Ist der diesmal richtig? Wenn nein, dann verbessert mich bitte!

    Warum sollte man den ableiten? Das hab ich gar nicht verstanden.
    Ich dachte structs kann man nicht erben lassen?!

    binary_function<baurecht_key, baurecht_key, bool>
    


  • hehejo schrieb:

    Ist der diesmal richtig?

    Nein, das ist wieder Käse.
    Üblicherweise macht man das so:

    bool operator <(const baurecht_key& rhs) {
        if(BetrNr != rhs.BetrNr)    return BetrNr < rhs.BetrNr;
        if(AnwKz != rhs.AnwKz)      return AnwKz < rhs.AnwKz;
        return UserName < rhs.UserName;
      }
    


  • Danke! Das muss ich mir noch ein bisschen durch den Kopf gehen lassen.
    Vielen Dank.. das hat mir sehr geholfen! 🙂 🙂


Anmelden zum Antworten