Tastatur Codes und Namen linken in beide Richtungen



  • Hi Leute,

    ich möchte gern meine Tastaturcode (char) mit den Namen der Tasten verknüpfen (std::string). Wie mach ich das am besten?

    Ich habe mich schon nach set, multiset und map, multimap erkundigt, aber so wie ich das verstehe funktioniert die Zuordnung da nur in 1 Richtung. Ich brauche aber beide Richtungen.
    char -> std::string
    std::string -> char
    Also zu einem Code (char) will ich den Namen (std::string) auslesen können und zu einem Namen (std::string) will ich den Code (char) haben.

    Zwei Maps kommen im Moment auch nicht in Frage, da ich ja dann auch beide synchron halten muss und die Fehlerquote ist mir zu hoch.

    Gruß
    Scarabol



  • boost.bimap



  • pack doch einfach beide maps in eine eigene Klasse, die sich um die Synchronität kümmert. Nach außen hin bietest du dann einfach zwei Methoden oder []Operatoren string -> char und char -> string an.

    greetz KN4CK3R



  • Boost hat eine bimap , das könnte's sein...


  • Mod

    Oder klassisch einfach zwei Felder. Tastaturcodes klingt so, als gäbe es höchstens 100-200, da könnte eine direkte Suche noch eine akzeptable Laufzeit haben und du hast dann bei sonstigen Zugriffen schön einfache Strukturen. Du kannst auch das Feld, welches häufiger durchsucht wird sortieren, dann hast du in diese Richtung sogar log(N) Suchzeit.



  • vorrausgesetzt er schreibts auch ordentlich und in bisschen auf speed.
    andererseits, bei den mengen kann er auch gleich nicht nur 2 arrays nehmen sondern gleich 4 um in beide richtungen alles sortiert haben


  • Mod

    Skym0sh0 schrieb:

    vorrausgesetzt er schreibts auch ordentlich und in bisschen auf speed.
    andererseits, bei den mengen kann er auch gleich nicht nur 2 arrays nehmen sondern gleich 4 um in beide richtungen alles sortiert haben

    Dann hat er ja wieder seine Synchronisationsprobleme 🙂 .

    (Der Smiley will heißen, dass das ein selbst gemachtes Problem ist. Siehe KN4CK3Rs Beitrag wie man so etwas idiotensicher lösen kann)



  • wow, danke für die vielen Antworten. Bin noch nicht so weit, aber um das Problemchen nochmal deutlicher zu machen.

    Ich hab zwei ziemlich lange Listen mit den Namen und den Codes für die einzelnen Tasten. Im Programm selber brauch ich dann Funktionen die mir für einen bestimmten Code den Tastennamen zurückliefern und für einen Tastennamen einen Code zurückliefern. Im Moment verfolge ich noch die bimap Methode. Wie ich das in einer eigenen Klasse machen kann, hab ich schon versucht aber kriegs nicht hin...

    Gruß
    Scarabol



  • Wenn boost.bimap ausscheidet kannst du ja vielleicht sowas verwenden. ShortCut könnte man zur Not durch std::pair ersetzen, aber ich würd´ das explizit ausformulieren.

    #include <string>
    #include <vector>
    #include <algorithm>
    #include <functional>
    
    // Klasse zum Ablegen der Key/Name Paare
    struct ShortCut // oder was auch immer
    {
       char Key;
       std::string Name;
    
       ShortCut() : Key( 0 )
       {
       }
    
       ShortCut( char Key, const std::string Name ) : Key( Key ), Name( Name )
       {
       }
    };
    
    // Prädikat zum Suchen nach Paaren anhand des Keys
    struct ShortCutEqualsKey : std::unary_function<ShortCut,bool>
    {
       char Key;
    
       ShortCutEqualsKey ( char Key ) : Key( Key )
       {
       }
    
       bool operator()( const ShortCut& op ) const
       {
          return op.Key == Key;
       }
    };
    
    // Prädikat zum Suchen nach Paaren anhand des Namen
    struct ShortCutEqualsName : std::unary_function<ShortCut,bool>
    {
       std::string Name;
    
       ShortCutEqualsName( const std::string& Name ) : Name( Name )
       {
       }
    
       bool operator()( const ShortCut& op ) const
       {
          return op.Name == Name;
       }
    };
    
    int main()
    {
       std::vector<ShortCut> ShortCuts;
       ShortCuts.push_back( ShortCut( 'a', "Aaaargh!" ) );
       ShortCuts.push_back( ShortCut( 'b', "Bäh!" ) );
    
       std::vector<ShortCut>::iterator i1 = std::find_if( ShortCuts.begin(), ShortCuts.end(), ShortCutEqualsKey ( 'a' ) );
    
       std::vector<ShortCut>::iterator i2 = std::find_if( ShortCuts.begin(), ShortCuts.end(), ShortCutEqualsName ( "Bäh!" ) );
    }
    


  • Oder irgendwas mit einem statischen mapping:

    //impl.h
    #ifndef INCLUDE_GUARD
    #define INCLUDE_GUARD
    
    unsigned char find(std::string const & s);
    std::string find(unsigned char c);
    
    #endif
    
    //impl.cpp
    #include "impl.h"
    
    namespace
    {
        typedef std::array<char const *, 42> lookup_table_type;
    
        lookup_table_type make_key_map()
        {
            lookup_table_type table;
            table[0] = "bla";
            table[1] = "blub";
            table[2] = "laber";
            //...
            table[41] = "das_wars";
            return table;
        }
    
        lookup_table_type const & get_key_map()
        {
            static lookup_table_type key_map = make_key_map();
            return key_map;
        } 
    }
    
    unsigned char find(std::string const & s)
    {
        lookup_table_type::const_iterator p = std::find(get_key_map().begin(), get_key_map().end(), s);
        if(p == get_key_map().end())
        {
            throw exception();
        }
        //evtl. noch einen offset auf die distanz rechnen, je nach mapping
        return std::distance(get_key_map().begin(), p);
    }
    
    std::string find(unsigned char c)
    {
        //evtl. noch einen offset auf c rechnen, je nach mapping
        if(c >= get_key_map().size())
        {
            throw exception();
        }
        return get_key_map()[c];
    }
    


  • @Tachyon

    Und wat machste, wenn die Keycodes nicht linear von 0-41 gehen?



  • Dann hast Du Pech. Aber hier fehlen Informationen für genaue Lösungen.



  • Die Codes sind nicht linear und haben auch keine Beziehungen zueinander...

    Gruß
    Scarabol


Anmelden zum Antworten