Complex multidimensional array in C++
-
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
-
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
-
Use a class or structure which has pointer for the second variable:
struct foo
{
int first;
int* second;
} fooArray[];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.
-
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.
-
:-O
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows. -- 6079 Smith W.
-
Use a class or structure which has pointer for the second variable:
struct foo
{
int first;
int* second;
} fooArray[]; -
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
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 abool operator<(const foo& other) const {}
method to the object, which is usually straight forward.
-
Thanks, just what the doctor ordered. Then I can add another member to the struct if I want. Nice and clean solution.
-
Thanks, just what the doctor ordered. Then I can add another member to the struct if I want. Nice and clean solution.
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
}
-
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
}
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 followsfor(auto [key, data] : IL9341Command) {
cout << "IL9341Comand [ 0x" << hex << key << " ] =";
for(auto cmd : data)
cout << " 0x" << hex << cmd;
cout << endl;
} -
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 followsfor(auto [key, data] : IL9341Command) {
cout << "IL9341Comand [ 0x" << hex << key << " ] =";
for(auto cmd : data)
cout << " 0x" << hex << cmd;
cout << endl;
}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 <.
-
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 abool operator<(const foo& other) const {}
method to the object, which is usually straight forward.
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.
-
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
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)
-
Use a class or structure which has pointer for the second variable:
struct foo
{
int first;
int* second;
} fooArray[];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; -
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;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].