|
I am going nuts with this test code.
Two dimensional array and my test objective is to find matching first element in the arrays.
It works fine "scanning " for 0xA as it should , goes crazy when I try to look for 0xB0.
I hope is is something stupid I am overlooking.
Hope any extra pairs of eyes will spot the problem.
#define COMMAND_LIST 16
int8_t ILI9341_Command_List[][COMMAND_LIST] = {
{ 0 },
{ 1 },
{ 4 },
{ 6, 7 , 8 },
{7},
{0xA,8,9,10,11,12},
{0xB0,8,9,10,11,12},
{9}
};
uint8_t ProcessCommand = 0xB0; int index = 0;
do {
cout << "SCAN ProcessCommand " << hex << +ProcessCommand << "@ index "
<< dec << +index << endl;
} while (ILI9341_Command_List[index++][0] != ProcessCommand);
|
|
|
|
|
because 0xb0 is negative in 8 bits? You are comparing a uint8_t (unsigned) with an int8_t (signed)
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
Thank you.
I knew I was getting too tired and that it was something STUPID I missed.
|
|
|
|
|
Compiling with all the warnings enabled (e.g. -Wall option, for g++ ) would help.
|
|
|
|
|
Thanks, I'll check that.
I do not want to make excuses , but I think I just copied the test code and missed the "u" , but I did get some - (minus) output when it went crazy.
|
|
|
|
|
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<FOO> foo2DArray[];
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
I think you meant this answer for Vaclav.
|
|
|
|
|
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Thanks, just what the doctor ordered.
Then I can add another member to the struct if I want.
Nice and clean solution.
|
|
|
|
|
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.
|
|
|
|
|
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; int* Data; } ILI9341Array[COMMAND_ARRAY];
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();
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;
}
modified 20-Jan-19 15:07pm.
|
|
|
|
|
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 <.
modified 20-Jan-19 15:09pm.
|
|
|
|
|
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; uint8_t Command; uint8_t c_d; uint8_t *Data; char *Name; char *Function; uint32_t delay = 0; char *RefPage; char *Notes; uint8_t temp[COMMAND_ARRAY] = {}; } 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 };
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 { uint8_t index; uint8_t Command; uint8_t c_d; uint8_t *Data; char *Name; char *Function; uint32_t delay; char *RefPage; char *Notes; uint8_t* temp; } ILI9341_CommandList[COMMAND_ARRAY] =
{ { 0, 0, 0, buffer, "command name" "Function", 100, RefPage, Notes, { 0x1, 0x0, 0xFF } }, {
}
};
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].
|
|
|
|
|
If your single element is unique, then maybe a map of vectors might be a better choice
e.g.
map<obj_a, vector<obj_b>>
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.
|
|
|
|
|
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.
|
|
|
|
|
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)
|
|
|
|
|
I am writing an article on best practices and in this article I am trying to formulate an hypothesis for which public functions eventually lead to most of the code design issues. It's not public functions per se, but more about inter-objects communication (messaging).
Established that encapsulation works fine for data abstract types, how would you define the situation in which stateful objects with well defined behaviours, do not have control on their states? Let's say in the best case scenarios, I have a well defined object with well defined behaviours, like Walk() and Run() but doesn't have control on when it walks and when it runs. Other objects will control when this object walks or runs. Let's now say that this object is used in a spaghetti codebase, where the reference to this object is injected indiscriminately. The object could potentially find itself walking or running at the wrong times. What I am trying to say is that encapsulation ensures the validity of the states, but cannot determine if the states are set at the right time.
How would you define this problem? I know how to solve it, I am just trying to understand if encapsulation is involved at all in this problem. Without public functions this problem wouldn't exist in the first place, but is the possibility of settings states at the wrong time a form of broken encapsulation?
modified 19-Jan-19 14:34pm.
|
|
|
|
|
I would bet a finite state machine would allow controlling the different states and their transitions.
667: The neighbour of the Beast
|
|
|
|
|
Are you asking if you might hit a brick wall while driving your car? Yes you might. Nonetheless your car is not faulty (at least before you hit the wall).
|
|
|
|
|
The car is fine, except for one nut behind the wheel.
Software rusts. Simon Stephenson, ca 1994. So does this signature. me, 2012
|
|
|
|
|
I really like this analogy and I will steal it for my article. However argument is that encapsulation eventually doesn't solve the problem its meant to solve and it's flawed. I know it's controversial, but after some research, I found out I am not the only one who got to this conclusion Object-Oriented Programming: A Disaster Story – Brian Will – Medium[^]. The controversial part is that people can argue that Encapsulation does its job (like in the case of the car), but OOP doesn't help, with its flexibility, to not break the car. If I can break the car easily, what's the point of the encapsulation to start with? Of course Encapsualtion as hiding of complexity is absolutely valid. Hence I think this problem I am trying to formalise, which is the possibility to set a valid state at the wrong time, may need another name. I will link the article here before to make it public, as I'd like your feedback.
modified 20-Jan-19 10:34am.
|
|
|
|
|