<map> oder doch nicht?



  • ich habe ein PacketFile (tcpdum, libpcap) und möchte feststellen, wie oft eine bestimmte IP Kombination aufgetreten ist.

    Ich habe mir das folgendermaßen gedacht:

    //...
    
    typedef struct flow_key_t {
        uint32_t src_addr;
        uint32_t dst_addr;
    };
    
    //...
    
    map<flow_key_t, uint64_t> flow_keys;
    
    for( pkt_num_t i=0; i<total_packets; i++ ) {
        pReader.nextPacket();
        flow_key_t flow_key = pReader.getFlowKey();
        flow_keys[ pReader.getFlowKey() ] += 1;
    }
    
    //...
    

    Leider geht das so nicht.

    Wie mache ich das am besten und ist <map> überhaupt richtig dafür?

    Viele Grüße
    Bastian



  • typedef struct flow_key_t {
        uint32_t src_addr;
        uint32_t dst_addr;
    };
    

    was hat das typedef da zusuchen?

    ich glaube eine minimal anforderung an für ein std::map key war das der typ einen operator< überladen hatt oder man über gibt std::map ein functor der entscheidet welches ob ein flow_key_t kleiner ist als ein anders flow_key_t

    kommst du damit weiter?



  • Gerard schrieb:

    typedef struct flow_key_t {
        uint32_t src_addr;
        uint32_t dst_addr;
    };
    

    was hat das typedef da zusuchen?

    Es soll ja nur eine Deklaration und keine Definition sein.

    Gerard schrieb:

    ich glaube eine minimal anforderung an für ein std::map key war das der typ einen operator< überladen hatt oder man über gibt std::map ein functor der entscheidet welches ob ein flow_key_t kleiner ist als ein anders flow_key_t

    kommst du damit weiter?

    Sorry, nicht wirklich. Wie erzeuge ich denn so einen "functor"?



  • also in c konnte man structuren du so deklarieren

    typedef struct { int a; } afoo;
    

    in c++ ist dann

    struct afoo{ int a; };
    

    hinzugekommen
    aber

    typedef struct afoo{ int a; };
    

    ist sinnloss

    zu nummer zwei http://www.sgi.com/tech/stl/Map.html
    struct ltstr ist der functor



  • Danke für den Tip. Ich habe das jetzt so gemacht, aber leider geht das irgendwie nicht.

    //...
    
    struct ltstr {
        bool operator()(flow_key_t& s1, flow_key_t& s2) const
        {
            return( (s1.src_addr+s1.dst_addr) < (s2.src_addr+s2.dst_addr) );
        }
    };
    
    map<flow_key_t, uint64_t, ltstr> flow_keys;
    
    //...
    

    Der Compierl sagt:

    trafana.cpp|78| error: template-argument `
    || analyzeAllPackets(std::vector<result_t, std::allocator<result_t> >&)::ltstr' 
    || uses local type `analyzeAllPackets(std::vector<result_t, 
    || std::allocator<result_t> >&)::ltstr'
    trafana.cpp|78| error: ISO C++ forbids declaration of `flow_keys' with no type
    

    Die frage ist natürluch, ob <map> für meinen Anwendungsfall überhaupt geeignet ist oder ob z.B. eine <hash_map> besser geeignet ist.
    Ich denke ich werde so ca. 100000 - 1000000 werte vorhalten müssen.



  • Nimm die struct ltstr mal aus der Funktion raus, dann klappt das. Template-Argumente dürfen, wie die Fehlermeldung schon sagt, keine lokal definierten Typen sein.



  • Ich habe die Definition von ltstr jetzt außerhalb der Definiert. Und nun bekomme ich aber folgende Meledung:

    /usr/include/g++/bits/stl_map.h: In member function `_Tp& std::map<_Key, _Tp,
       _Compare, _Alloc>::operator[](const _Key&) [with _Key = flow_key_t, _Tp =
       uint64_t, _Compare = ltstr, _Alloc = std::allocator<std::pair<const
       flow_key_t, uint64_t> >]':
    trafana.cpp:85:   instantiated from here
    /usr/include/g++/bits/stl_map.h:318: error: no match for call to `(ltstr) (
       const flow_key_t&, const flow_key_t&)'
    trafana.cpp:65: error: candidates are: bool ltstr::operator()(flow_key_t&,
       flow_key_t&) const
    


  • Du nimmst zum Vergleichen Referenzen auf nicht-konstante flow_key_t, map will den Funktor aber auch für Referenzen auf konstante flow_key_ts aufrufen können:

    bool operator()(const flow_key_t& s1, const flow_key_t& s2) const
    

    Oder, wenn flow_key_t sehr klein und schnell zu kopieren ist, ganz ohne Referenz:

    bool operator()(flow_key_t s1, flow_key_t s2) const
    

Anmelden zum Antworten