Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Complex multidimensional array in C++

Complex multidimensional array in C++

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestionc++data-structurestutorial
15 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Lost User

    Use a class or structure which has pointer for the second variable:

    struct foo
    {
    int first;
    int* second;
    } fooArray[];

    V Offline
    V Offline
    Vaclav_
    wrote on last edited by
    #6

    Thanks, just what the doctor ordered. Then I can add another member to the struct if I want. Nice and clean solution.

    L V 2 Replies Last reply
    0
    • V Vaclav_

      I can do multidimensional array , no problem. What I need is sort of " multidimensional array of single variable and variable length array ". The main array is defined / assigned (?) and of "fixed length" - three in example - for now. Of course I need to access all using pointer. How do I accomplish this ? PS I did try std:array , but it conflicts with "boost" - can't do for now.

            int Array \[3\]\[2\] = {{2, 5} , {3,1} , {4,9}}; multidimensional array OK 
      
        int Array\_Array \[ ??? \] = {
      		  {{1} ,{2, 5 ....}},      {single element} , {array...} 
      		  {{2} ,{2, 5 ...}},
      		  {{3} ,{2, 5....}}
        };
      

      Help will be appreciated. Cheers Vaclav

      K Offline
      K Offline
      k5054
      wrote on last edited by
      #7

      If your single element is unique, then maybe a map of vectors might be a better choice e.g.

      map>

      There is a requirement that obj_a implement operator<(). Basically if its not a basic type (e.g. int, double, string, etc), you need to add a

      bool operator<(const foo& other) const {}

      method to the object, which is usually straight forward.

      V 1 Reply Last reply
      0
      • V Vaclav_

        Thanks, just what the doctor ordered. Then I can add another member to the struct if I want. Nice and clean solution.

        L Offline
        L Offline
        Lost User
        wrote on last edited by
        #8

        Yes, if you are using a struct you can have many different items inside it. Also, as Daniel mentions below (to me) you may want to use a std::vector rather than a simple array.

        1 Reply Last reply
        0
        • V Vaclav_

          Thanks, just what the doctor ordered. Then I can add another member to the struct if I want. Nice and clean solution.

          V Offline
          V Offline
          Vaclav_
          wrote on last edited by
          #9

          Here is my test code. It is not very "dynamic" but will do for now. I may add the "Command" as a first element in Data array to make sure they match. Actually it would simplify things (a little ) - using just multidimensional array with first element being "Command". But I like the struct for future.... Now I need to modify usage of Command /Data....

          #define COMMAND_ARRAY 16
          struct ILI9341 {
          int Command; // ILI9341 commands
          int* Data; // ILI9341 data
          } ILI9341Array[COMMAND_ARRAY];

          // define/ assign Command
          int index = 0;
          int dataIndex = 0;
          int DefineCommand\[COMMAND\_ARRAY\] = { 0x0, 0x1, 0x4 };
          int DefineData\[\]\[10\] = { { 1, 2, 3, 4 }, { 5, 6, 7 }, { 9, 10, 11, 12, 13,
          		14 } };
          for (index = 0; index != 3; index++) {
          	ILI9341Array\[index\].Command = DefineCommand\[index\];
          

          #ifdef DEBUG
          cout << "ILI9341Array[" << dec << +index << "] Command 0x" << hex
          << ILI9341Array[index].Command << endl;
          #endif
          ILI9341Array[index].Data = DefineData[index];
          #ifdef DEBUG
          do {
          cout << "ILI9341Array[" << dec << +index << "] Data[" << dec
          << +dataIndex << "] 0x" << hex
          << ILI9341Array[index].Data[dataIndex] << endl;

          	} while (ILI9341Array\[index\].Data\[++dataIndex\]);
          	dataIndex = 0;
          

          #endif

          }
          
          K 1 Reply Last reply
          0
          • V Vaclav_

            Here is my test code. It is not very "dynamic" but will do for now. I may add the "Command" as a first element in Data array to make sure they match. Actually it would simplify things (a little ) - using just multidimensional array with first element being "Command". But I like the struct for future.... Now I need to modify usage of Command /Data....

            #define COMMAND_ARRAY 16
            struct ILI9341 {
            int Command; // ILI9341 commands
            int* Data; // ILI9341 data
            } ILI9341Array[COMMAND_ARRAY];

            // define/ assign Command
            int index = 0;
            int dataIndex = 0;
            int DefineCommand\[COMMAND\_ARRAY\] = { 0x0, 0x1, 0x4 };
            int DefineData\[\]\[10\] = { { 1, 2, 3, 4 }, { 5, 6, 7 }, { 9, 10, 11, 12, 13,
            		14 } };
            for (index = 0; index != 3; index++) {
            	ILI9341Array\[index\].Command = DefineCommand\[index\];
            

            #ifdef DEBUG
            cout << "ILI9341Array[" << dec << +index << "] Command 0x" << hex
            << ILI9341Array[index].Command << endl;
            #endif
            ILI9341Array[index].Data = DefineData[index];
            #ifdef DEBUG
            do {
            cout << "ILI9341Array[" << dec << +index << "] Data[" << dec
            << +dataIndex << "] 0x" << hex
            << ILI9341Array[index].Data[dataIndex] << endl;

            	} while (ILI9341Array\[index\].Data\[++dataIndex\]);
            	dataIndex = 0;
            

            #endif

            }
            
            K Offline
            K Offline
            k5054
            wrote on last edited by
            #10

            That's way too much typing. Consider:

            #include <iostream>
            #include <iomanip>
            #include <map>
            #include <vector>

            using namespace std;

            #define DEBUG

            int main()
            {
            map<int,vector<int>> IL9341Command = {{ {0x0, {{ 1, 2, 3, 4 }} },
            {0x1, {{ 4, 6, 7, }} },
            {0x4, {{ 9, 10, 11, 12, 13, 14 }} },
            {0xff, {{ 44, 55, 66, 77 }} } }};

            #ifdef DEBUG
            for(auto iter : IL9341Command) {
            cout << "IL9341Comand [ 0x" << hex << iter.first << " ] =";
            for(auto cmd : iter.second)
            cout << " 0x" << hex << cmd;
            cout << endl;
            }

            int \*data = IL9341Command\[0xff\].data(); // get access to raw vector data
            
            cout << "\\nCommand\[0xff\] data :";
            for(size\_t i = 0; i < IL9341Command\[0xff\].size(); i++)
                cout <<  " 0x" << data\[i\];
            cout << endl;
            

            #endif // DEBUG

            return 0;
            

            }

            You can access the command data directly if you know the key via IL941Command[key], without having to iterate through the array, and as shown above, access to the "raw data" can be gained by calling data() on the vector. If you have C++17 then you can simplify the for(auto iter ...) loop as follows

            for(auto [key, data] : IL9341Command) {
            cout << "IL9341Comand [ 0x" << hex << key << " ] =";
            for(auto cmd : data)
            cout << " 0x" << hex << cmd;
            cout << endl;
            }

            K 1 Reply Last reply
            0
            • K k5054

              That's way too much typing. Consider:

              #include <iostream>
              #include <iomanip>
              #include <map>
              #include <vector>

              using namespace std;

              #define DEBUG

              int main()
              {
              map<int,vector<int>> IL9341Command = {{ {0x0, {{ 1, 2, 3, 4 }} },
              {0x1, {{ 4, 6, 7, }} },
              {0x4, {{ 9, 10, 11, 12, 13, 14 }} },
              {0xff, {{ 44, 55, 66, 77 }} } }};

              #ifdef DEBUG
              for(auto iter : IL9341Command) {
              cout << "IL9341Comand [ 0x" << hex << iter.first << " ] =";
              for(auto cmd : iter.second)
              cout << " 0x" << hex << cmd;
              cout << endl;
              }

              int \*data = IL9341Command\[0xff\].data(); // get access to raw vector data
              
              cout << "\\nCommand\[0xff\] data :";
              for(size\_t i = 0; i < IL9341Command\[0xff\].size(); i++)
                  cout <<  " 0x" << data\[i\];
              cout << endl;
              

              #endif // DEBUG

              return 0;
              

              }

              You can access the command data directly if you know the key via IL941Command[key], without having to iterate through the array, and as shown above, access to the "raw data" can be gained by calling data() on the vector. If you have C++17 then you can simplify the for(auto iter ...) loop as follows

              for(auto [key, data] : IL9341Command) {
              cout << "IL9341Comand [ 0x" << hex << key << " ] =";
              for(auto cmd : data)
              cout << " 0x" << hex << cmd;
              cout << endl;
              }

              K Offline
              K Offline
              k5054
              wrote on last edited by
              #11

              Hmm. Not sure why the code didn't format properly within the <pre code="C++"> tags. I looked closely and there wasn't any tags in the code as posted. Also, how does one post code with preprocessor directives in column one without them turning into (h1) header lines? Edit: the format issue with the code was because I needed to convert "<" into <.

              1 Reply Last reply
              0
              • K k5054

                If your single element is unique, then maybe a map of vectors might be a better choice e.g.

                map>

                There is a requirement that obj_a implement operator<(). Basically if its not a basic type (e.g. int, double, string, etc), you need to add a

                bool operator<(const foo& other) const {}

                method to the object, which is usually straight forward.

                V Offline
                V Offline
                Vaclav_
                wrote on last edited by
                #12

                Well , I realize my way is too crude for today's standards. Yes, the "command(s)' are unique and direct access to data would be much cleaner than scanning. But I forgot that the command is actually "top level" - the same data can be actual "command" or "data" ( to be read). The clocking of the command (command or data) is different so I need some identifier for that. I need to rethink the method how to accomplish that - so far plain two dimensional array with "command" , " command or data flag " , "data" scheme looks simpler. Minor issue is - the "data" can be 0x0 - such as "0x4, 0x0, 0x7" etc.so plain scanning won't do. I need a break. Later.

                1 Reply Last reply
                0
                • V Vaclav_

                  I can do multidimensional array , no problem. What I need is sort of " multidimensional array of single variable and variable length array ". The main array is defined / assigned (?) and of "fixed length" - three in example - for now. Of course I need to access all using pointer. How do I accomplish this ? PS I did try std:array , but it conflicts with "boost" - can't do for now.

                        int Array \[3\]\[2\] = {{2, 5} , {3,1} , {4,9}}; multidimensional array OK 
                  
                    int Array\_Array \[ ??? \] = {
                  		  {{1} ,{2, 5 ....}},      {single element} , {array...} 
                  		  {{2} ,{2, 5 ...}},
                  		  {{3} ,{2, 5....}}
                    };
                  

                  Help will be appreciated. Cheers Vaclav

                  S Offline
                  S Offline
                  Stefan_Lang
                  wrote on last edited by
                  #13

                  Vaclav_ wrote:

                  PS I did try std:array , but it conflicts with "boost" - can't do for now.

                  I'm using both boost functinality and std::array without any problems, ever. What is the problem you are experiencing? Maybe you were too gracious with using statements and contaminating your global namespace?

                  GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

                  1 Reply Last reply
                  0
                  • L Lost User

                    Use a class or structure which has pointer for the second variable:

                    struct foo
                    {
                    int first;
                    int* second;
                    } fooArray[];

                    V Offline
                    V Offline
                    Vaclav_
                    wrote on last edited by
                    #14

                    Richard, I finally decided to use your suggestion and having a hard time initializing the pointer in the struct. Here is how it looks as of today

                    struct ILI9341 {
                    	uint8\_t index;  // tracking index
                    	uint8\_t Command; //
                    	uint8\_t c\_d;    // flag 0 command 1 data
                    	uint8\_t \*Data;  // data array
                    // data array format
                    // valid data count
                    // data...
                    // end marker
                    	char \*Name;     // command name
                    	char \*Function; // brief function description
                    	uint32\_t delay = 0; // delay in uS after command
                    	char \*RefPage;  // ILI9341 manual reference page
                    	char \*Notes;    // misc notes
                    	uint8\_t temp\[COMMAND\_ARRAY\] = {}; // kluge 
                    } ILI9341\_CommandList\[COMMAND\_ARRAY\];
                    

                    I did try this (C sample I found) , but that obviously does not work initializing multiple struct and I feel it defeats the pointer by making the temp array fixed length.

                    uint8_t temp[3] = { 0x1, 0x0, 0xFF };
                    //int g_thing1array[3] = { 3, 4, 5 }; C example
                    //thing g_thing1 = { 1, 2, g_thing1array };
                    ILI9341_CommandList[4].Data = temp;

                    L 1 Reply Last reply
                    0
                    • V Vaclav_

                      Richard, I finally decided to use your suggestion and having a hard time initializing the pointer in the struct. Here is how it looks as of today

                      struct ILI9341 {
                      	uint8\_t index;  // tracking index
                      	uint8\_t Command; //
                      	uint8\_t c\_d;    // flag 0 command 1 data
                      	uint8\_t \*Data;  // data array
                      // data array format
                      // valid data count
                      // data...
                      // end marker
                      	char \*Name;     // command name
                      	char \*Function; // brief function description
                      	uint32\_t delay = 0; // delay in uS after command
                      	char \*RefPage;  // ILI9341 manual reference page
                      	char \*Notes;    // misc notes
                      	uint8\_t temp\[COMMAND\_ARRAY\] = {}; // kluge 
                      } ILI9341\_CommandList\[COMMAND\_ARRAY\];
                      

                      I did try this (C sample I found) , but that obviously does not work initializing multiple struct and I feel it defeats the pointer by making the temp array fixed length.

                      uint8_t temp[3] = { 0x1, 0x0, 0xFF };
                      //int g_thing1array[3] = { 3, 4, 5 }; C example
                      //thing g_thing1 = { 1, 2, g_thing1array };
                      ILI9341_CommandList[4].Data = temp;

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #15

                      You cannot add initialisers to the struct definition, but only to actual instances of it. So it should rather be something like:

                      struct ILI9341 { // definition of the struct starts here
                      uint8_t index; // tracking index
                      uint8_t Command; //
                      uint8_t c_d; // flag 0 command 1 data
                      uint8_t *Data; // data array
                      // data array format
                      // valid data count
                      // data...
                      // end marker
                      char *Name; // command name
                      char *Function; // brief function description
                      uint32_t delay; // delay in uS after command
                      char *RefPage; // ILI9341 manual reference page
                      char *Notes; // misc notes
                      uint8_t* temp; // this should be a pointer to allow for variable length entries
                      } ILI9341_CommandList[COMMAND_ARRAY] =
                      { // actual instances in the array are initialised here
                      { // first entry in the structure array
                      0, // tracking index
                      0, // Command
                      0, // flag 0 command 1 data
                      buffer, // data array buffer declared elsewhere as BYTE buffer[some number]
                      "command name" // command name
                      "Function", // brief function description
                      100, // delay in uS after command
                      RefPage, // ILI9341 manual reference page
                      Notes, // misc notes
                      { 0x1, 0x0, 0xFF } // command array - you may need a counter somewhere to indicate
                      // how many entries are in this array
                      }, // end of the first entry
                      {
                      // other entries up to a maximum of COMMAND_ARRAY
                      }
                      };

                      And you can also fill in any of the fields later in the executable code by addressing struct entries as ILI9341_CommandList[n] where n is in the range [0..COMMAND_ARRAY-1].

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups