Suche geeigente Datenstruktur...



  • Hallo zusammen

    Ich komme in meinem Arduino Projekt nicht weiter, nun wende ich mich an euch.

    Was ich machen möchte:
    An eine Funktion sollen mehrere Objekte (vom der gleichen Klasse) übergeben werden. Je nach Sketch (es gibt mehrere) kann die Anzahl der so zu übergebenden Objekte jedoch unterschiedlich sein.

    Mein Versuch dies zu realisieren ging Richtung Arrays. Das Array kann ich erstellen (Deklarations-Teil / vor der Setup-Methode), mit meinen Objekten "füllen" (in Setup-Methode) und auch darauf zugreifen (im Loop-Methode).

    Will ich dieses Array nun an eine Funktion (konkret eine Init-Funktion einer selbst geschriebener Klasse) übergeben, scheitere ich immer daran, dass die Grösse des Arrays dieser Init-Funktion bereits bekannt sein muss! Meine "arme" Init-Funktion kann jedoch noch gar nicht wissen, wie viele Einträge das entegenzunehmende Array den hat.
    Damit ich in der Init-Funktion weiss, wie viele Einträge das Array hat, übergebe in neben dem Array auch noch ich die Anzahl Elemente als zweiten Parameter. Das ist "unschön", scheint jedoch bei C++ so zu sein (komme sonst eher aus der Java Ecke.).
    Übrigens, in der Init-Funktion meiner Klasse weise ich das Array nur einer Variablen zu. Andere Funtionen meiner Klasse suchen in diesem Array dann den passenden Eintrag um etwas damit zu machen - das ist aber eine andere Geschichte...

    Meine Fragen:

    • Geht das was ich will überhaupt mt einem Array?
    • Falls nicht, was für (einfache) Alternativen kommen in Frage (Varargs/Variadic, Struct, Vector, ...)?
    • Da das Ganze im Arduino zur Ausführung kommen soll, darf es keine allzu grosse Bibliothek sein. Es geht mir eiegntlich nur drum, eine vorher nicht genau bekannte Anzahl Objekte an die Init-Funtion zu übergeben.

    Vielen Dank für eure Hilfe 🙂



  • In C++ ist dafür der Standard-Container std::vector<T>, insbesondere da die Anzahl der Objekte bei dir ja unterschiedlich sind.
    Für Arrays fester Größe würde man ab C++11 (falls dein Arduino-Compiler es unterstützt) std::array<T, N> verwenden.

    In C ist aber die Übergabe eines Arrays mit getrennter Angabe der Größe der übliche Weg.



  • Soweit ich weiß können Vektoren (aus der Standard Lib) nicht auf Arduino verwendet werden oder nur auf bestimmten Arduino Controllern. Dynamische Speicherallokation sollte man auf so einem Ding generell nicht zu ausgiebig nutzen. Die Arduino Libs haben aber scheinbar ne eigene Implementierung davon: https://reference.arduino.cc/reference/en/libraries/vector/

    Andere Frage: Was steht in deinem Array drin? Warum ist die Größe dynamisch? Evtl. kannst du ein paar Details liefern, um sicherzugehen, dass es sich hier nicht um ein XY-Problem handelt.

    Im Allgemeinen kann man aber schon mal sagen: C++ auf dem Arduino ist kein richtiges C++. Du hast gewisse Limitierungen bedingt durch den Microcontroller. Auch im Internet etc. wirst du vor allem viel C & C++ gemischt finden.



  • @Leon0402 Arduinos bzw. die Entwicklungsumgebung dafür, gibt es von 8-Bit bis mindestens 32-Bit Controllern.

    Die großen haben genug Speicher.



  • Hallo zusammen
    Vielen Dank für die Antworten. Habe selbst auch noch ein wenig daran rumgebrütet. Jetzt habe ich das was ich eigentlich wollte. Untenstehend der Code (in der Arduino IDE 2.1.0):

    /*
    
      Polymorphismus Test in Arduino
    
      04.06.2023
    */
    
    // Imports
    // - Nichts spezielles
    
    // # Definiere drei Klassen
    // - Basis Klasse
    class Base
    {
      protected:
      int value = 0;
    
      public:
      void init(int _value)
      {
        value = _value;
      }
    
      virtual int getValue() 
      {
        return value;
      }
    };
    
    // - Klasse A, welche die Basis Klasse erweitert
    class A:public Base
    {
      public:
    
      int getValue() 
      {
        return value + 1;
      }
    };
    
    // - Klasse B, welche die Basis Klasse erweitert
    class B:public Base
    {
      public:
    
      int getValue() 
      {
        return value + 2;
      }
    };
    
    // # Definiere eine Klassen welche das spätere Array speichert und über die Arrayeinträge iteriert
    class Executer
    {
      private:
      Base** array;
      int arraySize;
    
      public:
      void init(Base* _array[], int _arraySize)
      {
        array = _array;
        arraySize = _arraySize;
      }
    
      void execute() 
      {
        for (int i = 0; i < arraySize; i++)
        {
          Base* current = array[i];
    
          Serial.print(F("- Arrayentry ["));
          Serial.print(i);
          Serial.print(F("]: "));
    
          Serial.println(current->getValue());
        }
      }
    };
    
    // # Erstellen je einer Instanz der Basisklasse und der beiden Klassen A und B
    Base* base = new Base();
    Base* a = new A();
    Base* b = new B();
    
    // # Erstellen je eines Arrays mit drei Einträgen
    Base* array[3];
    
    // # Erstellen der Instanz der Executor Klasse
    Executer executor;
    
    // # SETUP
    void setup()
    {
      // Seriallen Kanal initialisieren
      Serial.begin(115200);
    
      // ... und etwas herausschreiben
      Serial.println(F("> SETUP <"));
    
      Serial.print(F("Compilation date and time: "));
      Serial.print(__DATE__);
      Serial.print(F(" "));
      Serial.println(__TIME__);
      Serial.print(F("C++ compiler version: "));
      Serial.println(__cplusplus);
      Serial.println();
    
      // Die Instalzen initialisieren (jeweils mit dem gleichen Wert)
      base->init(2);
      a->init(2);
      b->init(2);
    
      // Array Elemente setzen
      array[0] = base;
      array[1] = a;
      array[2] = b;
    
      // Das Array zur speicherung an den Executor übergeben
      executor.init(array, 3);
    }
    
    // # LOOP
    void loop()
    {
      Serial.println(F("- Loop"));
      Serial.println(F("-------------------------------------------------------------------------------"));  
      executor.execute();
    
      delay(10000);
    }
    

    Und hier die Ausgabe:

    16:12:24.975 -> > SETUP <
    16:12:24.975 -> Compilation date and time: Jun  4 2023 16:12:21
    16:12:25.021 -> C++ compiler version: 201103
    16:12:25.021 -> 
    16:12:25.021 -> - Loop
    16:12:25.021 -> -------------------------------------------------------------------------------
    16:12:25.021 -> - Arrayentry [0]: 2
    16:12:25.021 -> - Arrayentry [1]: 3
    16:12:25.021 -> - Arrayentry [2]: 4
    

    Was meint ihr dazu? Könnte man das anders gestatlten?

    Vielen Dank weiterhin für Anregungen



  • @tomy27 Grds. ist bei embedded ja jedes Byte von Wert und eher NICHTS dynamisch. Gehe mal vom 8-bit-Arduino aus.
    Also will man eine beliebige Anzahl gar nicht, weil es irgendwann (sehr bald) den Platz sprengt. Gibt es eine typische und eine maximale Arraygröße? Dann würde ich ggf. 2 Methoden nehmen, die EXAKT einmal die typ Anzahl und einmal die max. übergeben, zzgl. Parameter, der sagt, wieviele (gleich oder weniger) von Relevanz sind.


Anmelden zum Antworten