I'm new here, although have a little programming experience.
Need a little help with the following array situation.
I have 16 arrays from patternA through to patternP each with 16 elements:
uint8_t patternA[16];
uint8_t patternB[16];
uint8_t patternC[16];
..
..
..
uint8_t patternP[16];
What I'm trying to achieve is an 'Array' of 'arrays' of sorts.
So when I create a 'for' loop I can cycle through and retrieve each element in each pattern.
Please see my example code. Its an example of going through ONLY two patterns, however rather than writing 16 of them, I would like to create a loop.
It looks like what you want is a 2D array unit_8 pattern[16][16];. Each row would be a pattern and each column would hold the 16 numbers for each pattern.
That is something I thought I may need, however I'm a little confused as to how I would declare it first off and then set it up in my recallPattern() function.
As I have 16 individual arrays 'patternA_' through to 'patternP_', my initial thought would be to put it into another array...
function up the loop and all you need is the pattern# enum parameter and its good to go.
this has a small fragility, if you go out of bounds on a pattern you will mess up or read from the next pattern. But if you can handle iteration over a fixed length buffer, it is one simple way to solve the problem.
You either put them in a 2-index array pattern_StepState[i][j] - as @handy andy advised you right at the start - and loop over the i index or i and j indices as you wish ...
... or you loop over a 1-index array pattern_StepState[k] with k going from 0 to 255.
True, you can't iterate over a nonsequential enum as far as I know. There are ways to make it work, of course, either directly or with a little extra effort.
there are loads of ways to do what you want, if you don't like the above ideas.
here is one
typedef uint8_t pat[16];
pat arrayofpats[16];
the above can be done with vectors as well.
you can also do objects.
struct s //or a class
{
uint8_t pat[16];
};
s arrayofs[16]; //or a vector, or a pointer, or any other stl container
you can still use an enum to name array/vector/container index to track them by names if you like.
and you can do 2-d constructs (the typedef masks this but is identical and the struct is similar though not exactly identical) like
uint8_t pat[16][16]; //or doubled vectors, or pointers, etc
you can also just wrap what you have.
vector<uint8_t*> arrayofexisting(16);
arrayofexisting[0] = patternA;
arrayofexisting[1] = patternB;
...
and iterate the vector when you need to iterate all the guys, and use their direct variable names when you need that. Best of both worlds, minimal effort to add to existing code.
Ok, what confuses me as how I would write that out for my code:
I'm looping through the pattern [16] (1 of 16 patterns), then patternA [16] (1 of 16 pattern variables), then stepState[16] (1 of 16 spots in the array)
I've made the areas that I need to index in bold.
Pattern = 1 of 16;
PatternA = 1 of 16 (A to P);
stepState[I] = 1 of 16;
which approach do you want to use, and I will try to show you.
you should mask that 16 as a constant. Magic numbers cause problems when you need to update / modify/ grow the code later.
from the looks of it you have a fair bit of code, making me recommend the vector of pointers approach at the end of my last post, but Im ok with anything.
that might look like this:
//don't need any if pattern number things.
clearPattern();
for(i = 0; i < magic; i++)
{
if(vecpattern[patternnumber][i] == 1) //vecpattern [n] is a pointer that is the array start location for PatternB or whatever, so you can dereference it exactly as if it were PatternB here
stepState[i] = 1;
}
you can get funky and have a class that contains pointers, one for stepstate and one for button, or you can have 2 decoupled vectors .. I dunno, its YOUR data structure. It looks to me like you would want to couple them, but ?? If you were doing it from scratch you wouldn't probably do it this way at all, this is a retro-fit that is simple. Just be aware of that for next time ... this is a band-aid.
if you do it with the class its just 1 more layer
vecpattern[patternnumber][buttonptr][i] and vecpattern[patternnumber][stepptr][i]
Thanks Jonnin. You'll have to excuse my language inexperience.
Yes, I have a fair bit of code all laid out in a very inefficient way!!! What I have works however its very long and feel that I can shrink it dramatically.
I tried using a struct above, to give an understanding as to how I could condense it, however that didn't work.
I need to have independent control over each, pattern, pattern(A-P), and stepState[1-16].
I edited my previous post to hopefully explain it better :)
ok, so wherever you define patternA ...
struct patternwrapper
{
uint8_t* stepptr;
uint8_t* buttonptr; //or is this bool?
};
vector <patternwrapper> somename(magicvaluefor16);
somename[0].stepptr = patternA_StepState;
somename[0].buttonptr = patternA_buttonFlag;
... dothisfor all of them...
...
then use it like above:
somename[pattern].stepptr[i] etc.
Does this make sense or do you need more?
/shrug I am not sure what you have at this point, buy my understanding is it worked but you had all the variables loose rather than contained nicely? Any of several of the above code can build a structure that works but most involve rewrites. What I just gave you patches in on top of what's there to provide a cleaner access point, that is ALL it really does. You can still use patternA etc variables where you need to, if you need to. Its all the same memory and which access point you use is just whatever is simple in the current code block...
a total re-write gets rid of the pointers of course. Then you don't have the risks of going out of bounds on anything. But that is a lot of work .. up to you if you think a do-over is needed.
I patched into what you had. This leads to a more invasive re-write.
If you are going to do that, you may as well make the struct members vectors to clean it up a bit. And use bool type, not uint8, for true/false values.
and I still recommend that enum for patternA etc names, to index into allthepatterns (or whatever you want to name it). If you find that useful anywhere ? looks like
allthepatterns[patternA].buttonFlag[i] //if this is meaningful. Here, the enum is a more natural 0,1,2,3.... values, not the skip list in the original idea, and if you add a max_value to the end of it, that can BE your (value of 16) above number and it will grow for you without any work if you insert a patternX value someday...