Problem mit einem Array.....



  • eupinkepank schrieb:

    Ich möchte zu einem späteren Zeitpunkt, in einer Funktion, das Array mit neuen Werten versehen...
    So in etwa wie:

    // array1 hat 8 Elemente
    array1[] = 0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80;
    

    Aber Du hast doch Dein Array mit 2 Elementen deklariert. Dann hat es auch nur zwei Elemente, nicht mehr und nicht weniger. Abgesehen davon, ist diese Syntax natürlich falsch.

    Falls Du andere Programmiersprachen gewohnt bist, sei Dir gesagt, dass es in C++ nur Indirektion gibt, wenn Du sie explizit verlangst. Damit meine ich, dass "array1" kein Zeiger und keine Referenz auf ein Array ist, sondern das Array selbst. Daher kannst Du nachträglich auch nicht die Länge ändern.

    Wenn Du "dynamische Arrays" haben willst, ist std::vector (aus dem <vector>-Header) das, was Du suchst:

    void gobbledigook(std::vector<int> & ref)
    {
      ref.clear();
      ref.push_back(11);
      ref.push_back(22);
      ref.push_back(33);
    }
    
    int main() {
      std::vector<int> foo;
      gobbledigook(foo);
      std::cout << foo.size() << std::endl;
    }
    

    Das mit dem push_back ist zugegebenermaßen weniger schön. Wenn Du Lust, etwas anderes auszuprobieren, kannst Du ja mal Boost.Assign testen. Damit könnte es so aussehen:

    void gobbledigook(std::vector<int> & ref)
    {
      ref.clear();
      ref += 11,22,33; // ::boost::assign::operator+=
    }
    

    Aber mit so etwas würde ich ehrlich gesagt nicht anfangen. Der kommende C++ Standard wird dann so etwas erlauben:

    void gobbledigook(std::vector<int> & ref)
    {
      ref = {11,22,33};
    }
    

    Gruß,
    kk



  • Warum nicht einfach so?

    static const int Values[4] = {0, 1, 2, 3};
    int temp[4];
    std::copy(Values, Values + 4, temp);
    


  • boost::array<int,4> a = { 1, 2, 3, 4 };
    // ...
    a = { 3, 4, 5, 6 };
    // ...
    


  • krümelkacker schrieb:

    eupinkepank schrieb:

    Ich möchte zu einem späteren Zeitpunkt, in einer Funktion, das Array mit neuen Werten versehen...
    So in etwa wie:

    // array1 hat 8 Elemente
    array1[] = 0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80;
    

    Aber Du hast doch Dein Array mit 2 Elementen deklariert. Dann hat es auch nur zwei Elemente, nicht mehr und nicht weniger. Abgesehen davon, ist diese Syntax natürlich falsch.

    Falls Du andere Programmiersprachen gewohnt bist, sei Dir gesagt, dass es in C++ nur Indirektion gibt, wenn Du sie explizit verlangst. Damit meine ich, dass "array1" kein Zeiger und keine Referenz auf ein Array ist, sondern das Array selbst. Daher kannst Du nachträglich auch nicht die Länge ändern.

    Wenn Du "dynamische Arrays" haben willst, ist std::vector (aus dem <vector>-Header) das, was Du suchst:

    void gobbledigook(std::vector<int> & ref)
    {
      ref.clear();
      ref.push_back(11);
      ref.push_back(22);
      ref.push_back(33);
    }
    
    int main() {
      std::vector<int> foo;
      gobbledigook(foo);
      std::cout << foo.size() << std::endl;
    }
    

    Das mit dem push_back ist zugegebenermaßen weniger schön. Wenn Du Lust, etwas anderes auszuprobieren, kannst Du ja mal Boost.Assign testen. Damit könnte es so aussehen:

    void gobbledigook(std::vector<int> & ref)
    {
      ref.clear();
      ref += 11,22,33; // ::boost::assign::operator+=
    }
    

    Aber mit so etwas würde ich ehrlich gesagt nicht anfangen. Der kommende C++ Standard wird dann so etwas erlauben:

    void gobbledigook(std::vector<int> & ref)
    {
      ref = {11,22,33};
    }
    

    Gruß,
    kk

    Das mit den 2 Elementen war nur in Beispiel 1 so... in Beispiel 2 waren es 8 um es deutlicher zu machen... im richtigen Programm sind es 30 Elemente aus denen das Array 126 verschiedene Zustände annehmen kann.

    Ich habe nun diese Lösung gewählt:

    array1[0] = 0x10;
    array1[1] = 0x20;
    ...
    array1[28] = 0x22;
    array1[29] = 0x33;
    

    Das sieht im Programm furchtbar aus, lässt sich aber wohl nicht umgehen.
    Das eigentliche Programm : Rund 50 Zeilen
    Die Deklarationsmöglichkeiten für dieses Array: Rund 4000 Zeilen... Supa 😃 Aber läuft.

    Danke für all die Infos und Hilfestellungen....



  • Wenn du unbedingt C-Arrays verwenden willst und wenn du so viele Werte zuweisen musst, geht es natürlich auch mit einer zusätzlichen Funktion.

    template<typename T, size_t size>
    void set_values(T destination[size], const T source[size]) {
     std::memcpy(destination, source, size*sizeof(T)); // keine Schleife
    }
    
    // usage:
    const int size=8;
    int array1[size] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
    set_values<int,8>(array1, {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80});
    

    alles ungetestet

    Wenn diese vielen Werte berechenbar sind, solltest du sie lieber während der Laufzeit berechnen lassen, ansonsten speicherst du sie in einer Datei ab und liest sie ein (bei einem richtigen Programm).



  • eupinkepank schrieb:

    Und zwar nicht mit einer "for Schleife", sondern möglichst in einem "rutsch", da das Array lediglich 126 verschiedene, statische Zustände annehmen kann.

    Stimmt so erstmal nicht. Ein Array aus zwei Ints kann auf einer üblichen 32-Bit-Plattform 2^64 Zustände annehmen. Wenn du nur 126 Zustände hast wäre zu überlegen ob du nicht einen char oder ein enum nehmen solltest - alles weitere wäre Platzverschwendung. Wenn du zwei Ints abhängig von den 126 Zuständen belegen willst wäre eine Funktion vielleicht gut, die das Belegen übernimmt.

    Was die grundsätzliche frage vom Belegen von genau zwei Ints in einem Array angeht kannst du es besonders elegant machen, indem du ein std::tr1::array<int, 2> (oder boost::array ) nimmst und es mit boost::list_of belegst.

    #include <boost/array.hpp>
    #include <boost/assign/list_of.hpp>
    
    int main()
    {
      using boost::assign::list_of;
    
      boost::array<int, 2> array1;
      array1 = list_of(0x10)(0x20);
      array1 = list_of(0x20)(0x1F);
    }
    


  • eupinkepank schrieb:

    ...im richtigen Programm sind es 30 Elemente aus denen das Array 126 verschiedene Zustände annehmen kann.

    Ich habe nun diese Lösung gewählt:

    array1[0] = 0x10;
    array1[1] = 0x20;
    ...
    array1[28] = 0x22;
    array1[29] = 0x33;
    

    Das sieht im Programm furchtbar aus, lässt sich aber wohl nicht umgehen.

    Das lässt sich ganz bestimmt umgehen. Du hast aber leider nicht sehr viel von dem verraten, was Du eigentlich machen willst. Und je weniger Du Dich mit C++ auskennst und je weniger Du über Dein eigentliches Problem verrätst, desto unwahrscheinlicher ist es, dass man Dir hilfreiche Antworten geben kann.

    eupinkepank schrieb:

    Das eigentliche Programm : Rund 50 Zeilen
    Die Deklarationsmöglichkeiten für dieses Array: Rund 4000 Zeilen... Supa 😃 Aber läuft.

    Wenigstens findest Du es selbst schlecht. :p



  • OK...
    Dann mehr zu dem Problem.. 🙂

    Ziel der Geschichte:

    Der Betrieb eines brandneuen Steuergerätes in einem älteren Auto.
    Das Steuergerät ist mit dem Rest des Autos via CAN Bus verbunden.
    Ich muss die Signale/Werte vom "alten" CAN Bus Protokoll in das neue CAN Bus Protokoll übersetzen und auch in die andere Richtung. (neu --> alt)
    Auf beiden Seiten werden 30 Werte (mein array) erwartet bzw. geliefert.
    Dieses Array kann maximal 126 unterschiedliche Eigenschaften/Ausprägungen annehmen.

    Ich weiß also: Wenn der Wert XY auf der "alten" Seite die Größe 123 hat, muss mein Array an die "neue" Seite eine ganz bestimmte Form annehmen.

    In diesem Schema ist keinerlei Dynamik... Es gibt nur 126 verschiedene "Layouts" von dem Array.

    Leider bin ich hier auf C++ angewiesen, da das ganze Programm später auf einem 16 MHz Controller quasi "standalone" laufen soll/muss.

    In jeder anderen Sprache, die ich so kenne, wären das 126 Zeilen Code für die möglichen Ausprägungen von diesem Array und ein paar Zeilen für die Logik... In C++ sieht das alles gaaaanz anders aus.

    Mein weiteres Problem: Ich kann nicht nach Belieben Bibliotheken inkludieren, da ich hier immer den Spagat zwischen Speicherbedarf und Performance machen muss und außerdem noch die Vorgaben des Herstellers einzuhalten habe.
    Dieser Mikrocontroller wird später in Serie produziert werden... Es ist daher zweitrangig, wie das Programm aussieht... Hauptsache ist: Es läuft schnell und sicher.

    Meine jetzige Lösung sieht echt scheiße aus 😃 :D, aber die läuft sauschnell und ich kann mit wenigen CPU Takten das zukünftige Layout des Arrays ermitteln und zuweisen + senden... Und bei einem 16 MHZ Controller bin ich über jeden eingesparten Takt dankbar, zumal der Mikrocontroller dort als Gateway fungiert und noch "nebenbei" rund 20KBit Daten in beide Richtungen 1:1 weiterleiten muss.

    Ich hoffe, dass ich das jetzt etwas näher bringen konnte.



  • Ich denke mit deiner Lösung hast du schon eine unschöne aber sau schnelle 😉 Vergiss nur nicht die Layouts "const" zu machen.

    Allerdings frage ich mich da nur, warum du 5000 Zeilen hast, wenn du nur 126 Layouts hast.

    const int array1[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
    

    Ein Array (Layout) pro Zeile ist doch schöner.



  • HighLigerBiMBam schrieb:

    Ich denke mit deiner Lösung hast du schon eine unschöne aber sau schnelle 😉 Vergiss nur nicht die Layouts "const" zu machen.

    Allerdings frage ich mich da nur, warum du 5000 Zeilen hast, wenn du nur 126 Layouts hast.

    const int array1[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
    

    Ein Array (Layout) pro Zeile ist doch schöner.

    Genau das ist mein Problem... ich weiß nicht wie das zu machen ist.
    Ich möchte das Array, so wie Du es gemacht hast, in einer Funktion, mit Werten versehen, und dann in einer 2. Funktion weiterverarbeiten. (In diesem Fall via CAN Bus versenden.

    mache ich es so:

    void senden(){
    
       //Mach was mit array1
    
    }
    void functionA(){
        const int array1[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
        senden();
    
    }
    

    So habe ich in "senden();" keinen Zugriff auf die Daten im Array1

    initialisiere ich das Array vorher im Kopf der Datei, so kann ich das Array nicht, wie hier in "functionA();" beschreiben.

    Ich hoffe, dass es nun verständlich ist, was ich will 😉
    Danke 🙂



  • Du muss den Array natürlich auch an die Funktion übergeben. Stichwort sind hier "Zeiger".

    void senden(const int *array){ //länge ist ja bekannt (30) ansonsten zweiten Parameter mit Länge mitgeben!
    
       //Mach was mit array1
    cout << array[0]; // genauso ansprechbar wie array nur da const nicht änderbar
    
    }
    void functionA(){
        const int array1[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
        senden(array1);
    }
    

    Den const int array1 kannst du aber auch mit array[0] -> array[29] ansprechen.#

    EDIT: Wenn du ihn unbedingt in der Funktion ändern musst, dann lasse const bei deklarierung und übergabe weg. Aber dann solltest du eh überlegen ob dein Design das richtige ist.



  • Servus!
    Danke.... Genau das habe ich gesucht.

    Nun siehts etwas besser aus im Programm...
    Nochmals: 1000Dank.
    👍 😋



  • eupinkepank schrieb:

    ...
    Leider bin ich hier auf C++ angewiesen, da das ganze Programm später auf einem 16 MHz Controller quasi "standalone" laufen soll/muss. In jeder anderen Sprache, die ich so kenne, wären das 126 Zeilen Code für die möglichen Ausprägungen von diesem Array und ein paar Zeilen für die Logik... In C++ sieht das alles gaaaanz anders aus.

    So ein Schwachsinn. Du weißt einfach nur nicht mit C bzw C++ umzugehen. Das schreit ja gerade danach, alles in vorberechnete Lookuptabellen/Hashtabellen abzulegen a la

    generated_tables.h

    #ifndef GENERATED_TABLES_H_INCLUDED
    #define GENERATED_TABLES_H_INCLUDED
    
    #define NUM_OF_SEQUENCES 126
    #define SEQUENCE_LENGTH  30
    
    struct entry {
      unsigned int hash_code;
      unsigned char bytes[SEQUENCE_LENGTH];
      unsigned int mapped_index; // index of corresponding CAN packet in other table
    };
    
    // sorted by hash_code
    extern const struct entry sequences_A[NUM_OF_SEQUENCES];
    extern const struct entry sequences_B[NUM_OF_SEQUENCES];
    
    #endif
    

    generated_tables.c

    #include "generated_tables.h"
    
    extern const struct entry sequences_A[NUM_OF_SEQUENCES] = {
      ...
    };
    
    extern const struct entry sequences_B[NUM_OF_SEQUENCES] = {
      ...
    };
    

    main.c

    #include "generated_tables.h"
    #include "hashfunc.h"
    
    ...
    
    struct entry const* lookup(
        unsigned char const* sequence,
        struct entry const* in_table )
    {
      unsigned int hash = hashfunc(SEQUENCE_LENGTH,sequence);
      struct entry const* ptr =
        my_lower_bound(in_table,in_table+NUM_SEQUENCES,hash);
      while (ptr<in_table+NUM_SEQUENCES
          && !compares_equal(SEQUENCE_LENGTH,sequence,ptr->bytes))
      {
        ++ptr;
      }
      return ptr;
    }
    
    ...
    
      unsigned char const* dat1 = ...;
      unsigned char const* dat2 =
        sequences_B[lookup(dat1,sequences_A)->mapped_index].bytes;
    
    ...
    

    u.s.w.


Anmelden zum Antworten