-         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 23

Thema: class mit bergebenen array Gren erstellen

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von HaWe
    Registriert seit
    09.10.2014
    Beitrge
    3.490

    class mit bergebenen array Gren erstellen

    Anzeige

    hi,
    ich mchte eine class tMenu erstellen, die per tMenu::init(a,b) zur Laufzeit einen array tMenu::array[a][b] erzeugen kann.

    In der Art:

    Code:
    class tMenu {
      
      protected:    
      
      public:      
        
        tMenu () : 
           {  }
    
           char CAPTLEN;
           char MENULEN;
        
           void init(char captlen,  char menulen) { 
             CAPTLEN = captlen;
             MENULEN = menulen;            
           }
    
           char list[MENULEN][CAPTLEN];
    };
    
    //
    klar geht das so nicht, wegen const fr array-Dimensionen -
    aber wie kriegt man es dennoch hin?

    - - - Aktualisiert - - -

    ich bin jetzt 1 Schritt weiter, ber assert -
    leider kann ich damit nur einen 1-dim array erstellen, keinen 2-dim.

    wie geht das denn nun wohl...?

    Code:
    #include <cassert>
     
    class tMenu {
      
      protected:         
            char * list;
            char MENULEN, CAPTLEN;      
      
      public:      
        
         tMenu (char menulen, char captlen) // constructor
         {
            assert(menulen > 0); 
            assert(captlen > 0); 
            list = new char[menulen]; 
        //  list = new char[menulen][captlen];   // alternat. >> error!
            MENULEN = menulen;
            CAPTLEN = captlen;
         }      
    
     
         ~tMenu() // destructor
         {
           // Dynamically delete the array we allocated earlier
           delete[] list ;
         }
    
    };
    Gendert von HaWe (04.12.2018 um 08:57 Uhr)
    ≠≡≈αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    22.06.2009
    Beitrge
    1.342
    Du bist schon ganz gut in der richtigen Richtung unterwegs.

    Ein multidimensional array in C++ ist eigentlich eine Liste von Pointer. D.h. list[0] z.B. liefert einen Pointer zurck, und auf diesem wird mit list[0][1] z.B. auf das 2. Element des Pointer zugegriffen.
    Deshalb kann man wie in Variante 1 das mit einer Schleife initialisieren.

    Variante 1
    Code:
    char * list;
    list = new char[menulen * captlen]
    Alternativ kann man auch einen aureichend groen Block Speicher allokieren.

    Variante 2
    Code:
    char ** list;
    list = new char*[menulen];
    for(int i = 0; i < captlen; i++)
    {
       list[i] = new char[captlen];
    }
    //Zugriff auf stelle x, y
    char val = list[x * captlen + y)
    Nachzulesen gibt es das z.B. hier: https://stackoverflow.com/questions/...in-c-using-new

    Ein Tipp auerdem: Solltest du das auf einem Mikrocontroller machen wollen solltest du auf new verzichten. Am PC wrde ich auch auf die Arrays verzichten und stattdessen einen std::vector<std::vector<char>> list verwenden. Dann muss man nmlich den Speicher nicht von Hand aufrumen und hat dynamische Gren geschenkt bekommen.

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von HaWe
    Registriert seit
    09.10.2014
    Beitrge
    3.490
    Zitat Zitat von shedepe Beitrag anzeigen
    Du bist schon ganz gut in der richtigen Richtung unterwegs.

    Ein multidimensional array in C++ ist eigentlich eine Liste von Pointer. D.h. list[0] z.B. liefert einen Pointer zurck, und auf diesem wird mit list[0][1] z.B. auf das 2. Element des Pointer zugegriffen.
    Deshalb kann man wie in Variante 1 das mit einer Schleife initialisieren.

    Variante 1
    Code:
    char * list;
    list = new char[menulen * captlen]
    Alternativ kann man auch einen aureichend groen Block Speicher allokieren.

    Variante 2
    Code:
    char ** list;
    list = new char*[menulen];
    for(int i = 0; i < captlen; i++)
    {
       list[i] = new char[captlen];
    }
    //Zugriff auf stelle x, y
    char val = list[x * captlen + y)
    Nachzulesen gibt es das z.B. hier: https://stackoverflow.com/questions/...in-c-using-new

    Ein Tipp auerdem: Solltest du das auf einem Mikrocontroller machen wollen solltest du auf new verzichten. Am PC wrde ich auch auf die Arrays verzichten und stattdessen einen std::vector<std::vector<char>> list verwenden. Dann muss man nmlich den Speicher nicht von Hand aufrumen und hat dynamische Gren geschenkt bekommen.
    danke,
    ich wollte es tatschlich auf einem ESP oder ARM machen, evtl. aber auch kompatibel zu einem Raspi.
    (schn ntl, wenn es spter auch auf AVRs luft.)
    vector kenne ich noch nicht, aber fr spter ist es wichtig, dass ich prinzipiell auf diese Weise den Zugriff habe auf 2-dim arrays, sowohl intern als auch dann von der aufrufenden Funktion:

    this->char list[10][20]={"line0", "line1", "line2", "line3",..., "line9"};
    Serial.println(this->list[k]);

    tMenu mymenu(10,20);
    strcpy(mymenu.list[5], "5 new testline", sizeof(testline));
    mymenu.list[5][0]='>';

    also Zugriff direkt auf die 2-dim Struktur, ohne immer rechnen zu mssen
    x * captlen + y

    Wie macht man es also am besten, cross-over-Plattform-kompatibel?
    Gendert von HaWe (04.12.2018 um 10:46 Uhr)
    ≠≡≈αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    22.06.2009
    Beitrge
    1.342
    Fr den ESP32 kann ich leider nichts sagen.
    Deshalb erlutere ich kurz die berlegung dahinter warum man auf einem Mikrocontroller in der Regel keinen Speicher dynamisch allokieren mchte.
    Das Problem dabei ist: Wenn man Speicher mit malloc oder new allokiert, wird dieser intern von der libc verwaltet. Diese schaut prinzipiell wo ist noch Speicher brig bzw. wo ist gengend speicher am Stck brig. Wenn man jetzt aber z.B. auf einem Atmega sehr wenig Speicher hat, wird dieser sehr schnell durchlchtert wenn man hufiger Speicher reserviert bzw. wieder frei gibt. Die libc implementiert zwar Algorithmen um diesen Speicher mglichst intelligent zu verwalten, das funktioniert nur mit sowenig Speicher nicht so super bzw. kann sehr viel Performance klauen. Zudem kann man nicht zur compilezeit sagen ob der Speicher berhaupt reicht.

    Bei greren Controllern wie dem ESP32 kann es durchaus mglich sein, dass effizient mit dynamisch allokiertem Speicher umgegangen werden kann.

    Ob es Sinn macht die Container aus der C++ Standardlib zu verwenden auf dem ESP32, msstest du auch noch mal recherieren. Diese machen einem das Leben wesentlich leichter, kosten aber natrlich auch etwas mehr Speicher und CPU Leistung.

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von HaWe
    Registriert seit
    09.10.2014
    Beitrge
    3.490
    neinnein, ich habe "nur" einen esp8266, alternativ M0, M3, M4, aber es wre ntl schn auch auf dem Raspi und auch AVR Mega oder gar Nano: grundstzlich eben Plattform-unabhngig.
    Das mit den Lchern verstehe ich, aber es wird vorraussichtlich nicht so hufig passieren mit dem destructor, viel hufiger werden constructors nacheinander aufgerufen werden.

    Was wrdest du also vorschlagen fr die Erzeugung von 2-dim arrays
    - wichtig, wie gesagt, ist der direkte Zugriff auf alle einzelnen Speicherzellen beider Dimensionen, ohne so etwas wie
    x * captlen + y
    rechnen zu mssen,
    so z.B. wie bereits oben erwhnt

    tMenu mymenu(10,20);
    strcpy(mymenu.list[5], "5 new testline", sizeof(testline));
    mymenu.list[5][0]='>';
    ≠≡≈αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    22.06.2009
    Beitrge
    1.342
    Mein Vorschlag wre: Mache eine Klasse, wie du sie jetzt schon hast. Lege aber die Instanzen des Klassen auf dem Stack an.
    Also statt tMenu * mymenu = new tMenu(); lieber tMenu myMenuy;

    Dann solltest du die Gren statt ber den Konstruktor lieber als C++ Template bergeben. Dann knnen die zur Compilezeit ersetzt werden.
    Dann kannst du dein array auch mit: char mylist[x][y] anlegen.

    Beispiel
    Code:
    template <int x_size,int y_size>
    class Menu{
         private:
             char list[x_size][y_size];
         
    
    
    };
    
    Verwendung:
    Menu<10,20> myMenu;
    Noch ein Hinweis zum Rechnen (Falls das mal relevant fr dich werden sollte):
    Einfach den Zugriff in einer Methode Kapseln die das Rechnen macht und dann ist das auch gar nicht so schlimm

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von HaWe
    Registriert seit
    09.10.2014
    Beitrge
    3.490
    hmm, vielen lieben Dank, das klingt alles wirklich gut. Ich muss jetzt nur noch alles ineinander kriegen, tatschlich ist dieses hier erst mein zweites C++ OOP Projekt berhaupt.

    Erstmal, ist private besser als protected? Oder geht beides? Ist protected evtl flexibler fr Zugriffe von "auen" und "innen"?

    dann zu
    Also statt tMenu * mymenu = new tMenu(); lieber tMenu myMenu;
    ja: so hatte ich es ja auch vor als Instanz: tMenu myMenu;


    Das wre jetzt, was ich aus deinen Vorschlgen verstanden habe, mit int16_t als Kompromiss zw. char und int fr die sizes,
    allerdings vllig unklar wie der constructor jetzt aussehen muss , also wie genau ich den array samt seines Speicherbedarfs dynamisch erzeugen soll:

    Code:
    class tMenu{
       private :
    
           int16_t  MENULEN, CAPTLEN;      
           char list[MENULEN][CAPTLEN];
    
       public:      
        
         tMenu (int16_t menulen, int16_t captlen) // constructor
         {       
            MENULEN = menulen;
            CAPTLEN = captlen;
    
            // .... und wie weiter hier?
         }      
    
     
         ~tMenu() // destructor
         {
           // Dynamically delete the array we allocated earlier
           delete[] list ;
         }
    
    };
    Edit:
    zustzlich rechnen mchte ich ja nicht, weder innerhalb der Klasse noch auerhalb bei Verwendung von Instanzen.
    Instanziierung wrde ich auch am liebsten ohne template machen, wenn mglich, einfach per

    tMenu mymenu(10,20);

    fr solche Manipulationen in main oder loop:

    strcpy(mymenu.list[5], "5 new testline", sizeof(testline));
    mymenu.list[5][0]='>';
    Gendert von HaWe (04.12.2018 um 13:43 Uhr)
    ≠≡≈αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von HaWe
    Registriert seit
    09.10.2014
    Beitrge
    3.490
    wie muss denn also dafr der construcor fr den "echten" dynamischen 2-dim array aussehen?

    denn diese beiden Methoden

    Code:
    char * list;
    list = new char[menulen * captlen]
    
    char ** list;
    list = new char*[menulen];
    for(int i = 0; i < captlen; i++)
    {
       list[i] = new char[captlen];
    }
    
    //Zugriff auf stelle x, y
    char val = list[x * captlen + y)
    scheinen ja nur jew. einen 1-dim array zu erzeugen....?
    ≠≡≈αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von HaWe
    Registriert seit
    09.10.2014
    Beitrge
    3.490
    also dies funktioniert nicht

    Code:
    class tMenu {
      
      protected:    
            int16_t  MENULEN, CAPTLEN;     
            char    list[MENULEN][CAPTLEN];      
                  
      
      public:      
        
         tMenu (int16_t menulen, int16_t captlen) // constructor
         {
            MENULEN = menulen;
            CAPTLEN = captlen;
           
            list = new char*[menulen];
            for(int i = 0; i < captlen; i++)
            {
              list[i] = new char[captlen];
            }
            
         }      
    
    };
    exit status 1
    invalid use of non-static data member 'tMenu::MENULEN'

    so auch nicht:
    Code:
    class tMenu {
      
      protected:    
            int16_t  MENULEN, CAPTLEN;                  
            char    **list;      
      
      public:      
          
         tMenu (int16_t menulen, int16_t captlen) // constructor
         {
            MENULEN = menulen;
            CAPTLEN = captlen;
           
            list = new char*[menulen];
            for(int i = 0; i < captlen; i++)
            {
              list[i] = new char[captlen];
            }
            
         }      
    }; 
    
    tMenu mymenu(20,10);
    //...
      char test[15]="5 newline_";
      strcpy(mymenu.list[5], test);
    exit status 1
    'char** tMenu::list' is protected

    dies funktioniert offenbar, von auen aufgerufen

    Code:
    class tMenu {
      
      protected:    
            int16_t  MENULEN, CAPTLEN;                  
              
      
      public:      
         char    **list;     
         tMenu (int16_t menulen, int16_t captlen) // constructor
         {
            MENULEN = menulen;
            CAPTLEN = captlen;
           
            list = new char*[menulen];
            for(int i = 0; i < captlen; i++)
            {
               list[i] = new char[captlen];
            }
            
         }      
    
     
         ~tMenu() // destructor
         {
           // Dynamically delete the array we allocated earlier
           delete[] list ;
         }
    
    };
     
    
    tMenu mymenu(20,10);
    
    void setup(void)
    {
      // Start Serial
      
      Serial.begin(115200);
      delay(2000); // wait for Serial()
      Serial.println("Serial started");
      
      char test[15]="5 newline_";
      strcpy(mymenu.list[5], test);
      Serial.println(mymenu.list[5]);
      mymenu.list[5][0]='>';
      Serial.println(mymenu.list[5]);
      //
    }
    - - - Aktualisiert - - -

    was allerdings nicht funktioniert, ist die Benutzung der array Zellen intern,
    z.B. per init cstrings reinkopieren:


    Code:
    class tMenu {
      
      protected:    
            int16_t  MENULEN, CAPTLEN; 
            char buf[20];                 
              
      
      public:      
         char    **list;     
         tMenu (int16_t menulen, int16_t captlen) // constructor
         {
            MENULEN = menulen;
            CAPTLEN = captlen;
           
            list = new char*[MENULEN];
            for(int i = 0; i < CAPTLEN; i++)
            {
              list[i] = new char[CAPTLEN];
            }        
         }      
         
         void init() {
            for(int i=0; i<MENULEN; i++) {
               sprintf(buf,"%d line %d", i);
               strcpy(list[i], buf);
            }
         }
    
     
         ~tMenu() // destructor
         {
           // Dynamically delete the array we allocated earlier
           delete[] list ;
         }
    
    };
    
    //
      tMenu mymenu;
      mymenu.init();
    Exception (29):
    epc1=0x40205d7b epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

    ctx: cont
    sp: 3fff0250 end: 3fff0550 offset: 01a0

    >>>stack>>>
    3fff03f0: 00000022 3ffef4fc 00000028 402025a3
    3fff0400: 3ffe9d80 4010560e feefeffe feefeffe
    3fff0410: feefeffe feefeffe 00000000 4000050c
    3fff0420: 3fffc278 40105464 3fffc200 00000022
    3fff0430: 3fff0440 feefeffe feefeffe feefeffe
    3fff0440: 402040f9 00000030 0000001e ffffffff
    (usw...)
    <<<stack<<<
    - - - Aktualisiert - - -

    auch so geht es nicht:
    Code:
       void init() {
            for(int i=0; i<MENULEN; i++) {
               sprintf(buf,"%d line %d", i);
               strcpy(list[i*CAPTLEN], buf);
            }
         }
    wie muss man jetzt stattdessen this->init() richtig codieren?
    Gendert von HaWe (05.12.2018 um 10:00 Uhr)
    ≠≡≈αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von HaWe
    Registriert seit
    09.10.2014
    Beitrge
    3.490
    also noch mal 1 Schritt zurck:
    offenbar lsst sich list[MENULEN][CAPTLEN] intern noch nicht richtig ansprechen, indem man Werte fr die Zellen , z.B. cstrings, in die Zellen reinkopiert, genau wie man es von auen per Aufruf einer Instanz knnen soll:

    Code:
      strcpy(mymenu.list[5], test);  
      Serial.println(mymenu.list[5]);
      mymenu.list[5][0]='>';
      Serial.println(mymenu.list[5]);
    wie muss man intern in der class einen 2-dim array
    list[MENULEN][CAPTLEN]
    erzeugen, damit man auch intern mit Objekt-Methoden seine Zellen einzeln ansprechen und manipulieren kann?
    Noch nicht einmal mit "rechnen"
    list[i*CAPTLEN]...
    geht es ja bisher...?



    Code:
    class tMenu{
       private :
    
           int16_t  MENULEN, CAPTLEN;      
          
    
       public:      
        
         tMenu (int16_t menulen, int16_t captlen) // constructor
         {       
            MENULEN = menulen;
            CAPTLEN = captlen;
    
            // .... wie ist public list[MENULEN][CAPTLEN] zu erzeuen?     }      
    
    
    };
    Gendert von HaWe (05.12.2018 um 17:42 Uhr) Grund: typo
    ≠≡≈αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

Seite 1 von 3 123 LetzteLetzte

hnliche Themen

  1. Change member of a class from another class
    Von iciwi im Forum Arduino -Plattform
    Antworten: 1
    Letzter Beitrag: 27.08.2016, 10:45
  2. neues Byte aus Byte-Array erstellen
    Von BoondockDuck im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 06.09.2008, 08:53
  3. Bits in smtlichen Gren :)
    Von squelver im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 0
    Letzter Beitrag: 22.11.2007, 13:02
  4. SMD-Gren fr SMD-Anfnger
    Von jeybo im Forum Elektronik
    Antworten: 22
    Letzter Beitrag: 29.08.2006, 08:04
  5. Eagle - Gren
    Von BlackDevil im Forum Konstruktion/CAD/Sketchup und Platinenlayout Eagle & Fritzing u.a.
    Antworten: 9
    Letzter Beitrag: 27.03.2006, 23:58

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhnge hochladen: Nein
  • Beitrge bearbeiten: Nein
  •