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[];

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

    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 1 Reply Last reply
    0
    • 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