Wie loope ich durch ein struct array mit function pointern?



  • Hallo,
    ich versuche ein Programm zu schreiben, welches abhängig von einem Counter eine Funktion über einen Funktion Pointer aufruft. Das ganze soll verschiedene Funktionen
    über die Länge eines Tastendrucks (welche über einen internen Timer gemessen wird) ermöglichen. Leider verstehe ich nicht, wie ich durch ein struct array loope und dann den jeweiligen function pointer auslöse. Hat jemand eine Idee?

    STL Libraries wie map und algorithm stehen nicht zur Verfügung da sie in meiner Umgebung (mbed) nicht oder nicht vollständig unterstützt werden.

    Vielen Dank,
    Jens

    #include <iostream>
    
    struct action
    {
        int counter_limit;
        void (*transition)(void);
    };
    
    void state1() {
        std::cout << __func__;
    }
    void state4() {
        std::cout << __func__;
    }
    void state8() {
        std::cout << __func__;
    }
    
    const action action_table[] =
    {
        { 4, state1 },
        { 8, state4 },
        { 11, state8 },
    };
    
    int STATE =0;
    
    void stateEval(int counter) {
    
    if action_table[counter].counter_limit <= counter && action_table[counter+1].counter_limit > counter{
      return transition();
    }
    
    int main()
    {
      for (int counter = 0 ; counter < 11; ++counter)
            stateEval(counter);
    
        return 0;
    


  • Und was ist jetzt das Problem?



  • Also ein Problem ist auf jeden Fall das if-statement Zeile 32--34, welches frei im Raum steht und in keiner Funktion drinsteht. Was genau erwartest Du wann das ausgeführt wird?



  • Ja, sorry, ich hätte das Problem besser beschreiben sollen. Die Funktion stateEval funktioniert so nicht. Ich verstehe nicht, wie ich den jeweiligen Funktion Pointer setzte, wenn die Bedingung in stateEval erfüllt ist.



  • "funktioniert nicht"? Aha



  • void stateEval(int counter)
    {
        size_t size = sizeof(action_table) / sizeof(action_table[0]);
        for (size_t i=0; i < size; i++)
        {
            const action &a = action_table[i];
            if (counter < a.counter_limit)
            {
                a.transition();
                return;
            }
        }
    }
    

    (solange die action_table sortiert nach dem counter_limit ist)

    s. ideone - Code



  • Vielen Dank Th69!!! Das ist genau das, was ich implementieren wollte, aber nicht konnte.
    Vielleicht noch eine Frage dazu:

    const action &a = action_table[i];
    

    Was genau passiert da? Instanziieren von "a" vom datentyp "action" und Referenzieren auf die "i-te" Zeile der action_table?



  • a ist einfach eine (konstante) Referenz auf "action_table[i]", um diesen Ausdruck im folgenden nicht mehrfach schreiben zu müssen (ist m.E. auch lesbarer).



  • Ok, prima, verstanden. Jetzt würde ich das Ganze gerne noch in eine Klasse packen, so dass ich im Programm nur die action_table definieren und dann die stateEval Methode aus der State_Caller Klasse auf rufen muß. Wie kann ich die action_table für die Klasse sichtbar machen?

    Vielen Dank!
    Jens

    #include <iostream>
    
    class State_Caller{
      State_Caller(){};
      ~State_Caller(){};
        public:
          struct action
          {
              int counter_limit;
              void (*transition)(void);
          };
    
          int STATE =0;
          void stateEval(int counter)
          {
              size_t size = sizeof(action_table) / sizeof(action_table[0]);
              for (size_t i=0; i < size; i++)
              {
                 const action &a = action_table[i];
                  if (counter < a.counter_limit)
                  {
                      a.transition();
                      return;
                  }
              }
          }
    };
    
    void state1() {
        std::cout << __func__;
    }
    void state4() {
        std::cout << __func__;
    }
    void state8() {
        std::cout << __func__;
    }
    
    const action action_table[] =
    {
        { 4, state1 },
        { 8, state4 },
        { 11, state8 },
    };
    
    int main()
    State_Caller sc;
    
    {
      for (int counter = 0 ; counter < 11; ++counter)
            sc.stateEval(counter);
    
        return 0;
    }
    


  • Vielleicht sollte ich nochmal beschreiben, was ich erreichen will. Ich möchte eine Library schreiben, der ich eine Liste aus Callbacks und Zeitspannen übergebe und die dann einen Function Pointer zurück gibt.
    Mir ist schon klar, das hier niemand den kompletten Code für mich herunterschreiben will - auch wenn das Implementieren der stateEval Funktion schon extrem hilfreich war. Für Hinweise was ich mir anschauen muß, Keywords, links, oder konkrete Beispiele wäre ich sehr dankbar.

    Gruß,
    Jens



  • jensstruemper schrieb:

    Mir ist schon klar, das hier niemand den kompletten Code für mich herunterschreiben will

    1. du hast bescheidene C++ Kenntnisse
    2. STL willst/kannst du nicht verwenden => C mit Klassen
    3. Arrays sind dir völlig fremd
    4. Du beschreibst dein Problem nicht - auch auf Nachfragen hin kommt so gut wie nichts
    5. der gezeigte Sourcecode hat nur eine gewisse Ähnlichkeit mit dem Echten. Es ist unmöglich zu sagen, was jetzt Tipp- oder Kopierfehler und was das Problem ist

    Was erwartest du also? Lerne, wie man Arrays verwendet!



  • @jensstruemper: Da du "struct action" innerhalb der Klasse State_Caller definiert hast, müßtest du immer (außerhalb der Klasse)

    const State_Caller::action action_table[] =
    

    schreiben.
    Definiere daher besser die Struktur auch außerhalb der Klasse (am besten packe alles in einen eigenen Namensbereich (namespace)).
    Das gehört aber zu den Grundlagen und solltest du beherrschen, gerade wenn du eigene Libraries entwickeln möchtest...



  • @manni66

    1. du hast bescheidene C++ Kenntnisse

    da hast du (leider) völlig recht

    1. STL willst/kannst du nicht verwenden => C mit Klassen

    STL kann ich nicht verwenden, da das meine Umgebung nicht ermöglicht. --> uC Project

    1. Arrays sind dir völlig fremd

    ok, in Verbindung mit OO hab ich da so meine Probleme

    1. Du beschreibst dein Problem nicht - auch auf Nachfragen hin kommt so gut wie nichts

    Ich kann es leider nicht besser beschreiben. Ich habe eine Idee wie ich meine Library benutzen möchte, das entsprechende Knowhow zur Implementierung fehlt. Ich finde es relativ schwierig von den OOP Grundlagen zur der Lösung eines konkreten Problems zu kommen.

    1. der gezeigte Sourcecode hat nur eine gewisse Ähnlichkeit mit dem Echten. Es ist unmöglich zu sagen, was jetzt Tipp- oder Kopierfehler und was das Problem ist

    Naja, das ist schon der "echte" Code, bis zu dem Punkt wo ich mir nicht mehr weiterkomme.
    Bisher besteht mein Projekt aus endlos untereinander geschriebenen Funktionen und statischen Konstrukten. Da dies langsam unübersichtlich wird, wollte ich anfangen, einzelne Funktionen in libraries auszulagern.

    @Th69: Danke für den Hinweis! Ich werde mir die entsprechenden Grundlagen zu Gemüte führen.



  • Dies hier ist Lösung meines Problems. Nicht besonders elegant, aber es funktioniert. Mein Compiler unterstützt kein C++11, daher kann ich keine initializer lists, auto etc, benutzen welches den code vereinfachen würde. Dank nochmal für die Hilfe und kritische Fragestellungen 😉

    #include <iostream>
    
    struct action
    {
        int counter_limit;
        void (*transition)(void);
    };
    
    struct action_list
    {
        size_t size;
        const action *table;
    };
    
    class ButtonHandler {
    public:
        ButtonHandler(std::size_t table_size, const action* begin) {
            mTable.size = table_size;
            mTable.table = begin;
        }
    
        void operator()(int counter) const {
            const action *a = mTable.table;
            for (std::size_t i=mTable.size; i; --i, ++a) {
                if (counter < a->counter_limit) {
                    a->transition();
                    return;
                }
            }
        }
    private:
        action_list mTable;
    };
    
    void state1() {
        //std::cout << __func__;
        printf("state1");
    }
    void state4() {
        //std::cout << __func__;
        printf("state4");
    }
    void state8() {
        //std::cout << __func__;
        printf("state8");
    }
    
    const action action_table[] =
    {
        { 4, state1 },
        { 8, state4 },
        { 11, state8 },
    };
    
    int main()
    {
        const ButtonHandler btn_h(
                sizeof(action_table)/sizeof(action_table[0]),
                action_table
        );
    
        for (int counter = 0 ; counter < 11; ++counter)
            btn_h(counter);
    }
    

Log in to reply