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.
  • D Daniel Pfeffer

    If you have an two-dimensional array where each row has a differing number of elements, why not use a std::vector?

    std::vector foo2DArray[];

    Freedom is the freedom to say that two plus two make four. If that is granted, all else follows. -- 6079 Smith W.

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

    I think you meant this answer for Vaclav.

    D 1 Reply Last reply
    0
    • L Lost User

      I think you meant this answer for Vaclav.

      D Offline
      D Offline
      Daniel Pfeffer
      wrote on last edited by
      #5

      :-O

      Freedom is the freedom to say that two plus two make four. If that is granted, all else follows. -- 6079 Smith W.

      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
        #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