Reputation: 560
I'm looking for an easy workaround for two-dimensional arrays of dynamic size as parameters that literally students from the 5th grade can easily use. I'm currently writing a library for a micro controller workshop and want it to be as easy as possible to use without having to explain pointers, templates and such simply because there's not the time to do that.
I have the following class, called LEDBitmap
, which has a maximum width of 8 due to constraints in another library and represents a bitmap of ones and zeros for an LED matrix:
The header file:
#ifndef LEDBITMAP_H
#define LEDBITMAP_H
#include <Arduino.h>
class LEDBitmap
{
public:
LEDBitmap(uint8_t width, uint8_t height, uint8_t data[][8]);
LEDBitmap(uint8_t width, uint8_t height);
virtual ~LEDBitmap() {
delete [] _data;
};
public: //methods
uint8_t* getBitmap();
uint8_t getPixelValue(uint8_t x, uint8_t y) {
return _data[y][x];
};
void setPixelValue(uint8_t x, uint8_t y, uint8_t value) {
_data[y][x] = value;
};
uint8_t getHeight() {
return _height;
};
uint8_t getWidth() {
return _width;
};
uint8_t getSize() {
return _width * _height;
};
void clear();
private: //members
uint8_t _width;
uint8_t _height;
uint8_t _data[][8];
};
#endif
And the cpp file:
#include "LEDBitmap.h"
LEDBitmap::LEDBitmap(uint8_t width, uint8_t height) {
_width = width;
_height = height;
_data = new uint8_t[width][height];
clear();
}
LEDBitmap::LEDBitmap(uint8_t width, uint8_t height, uint8_t data[][8]) {
_width = width;
_height = height;
_data = data;
}
uint8_t* LEDBitmap::getBitmap() {
uint8_t result[_height];
for (uint8_t h = 0; h < _height; h++) {
uint8_t binary = 0;
for (uint8_t w = 0; w < _width; w++) {
binary |= _data[h][w] << (_width - w+1);
}
result[h] = binary;
}
return result;
}
void LEDBitmap::clear() {
for (uint8_t h = 0; h < _height; h++) {
for (uint8_t w = 0; w < _width; w++) {
_data[h][w] = 0;
}
}
}
My problem is the first constructor where the parameter uint8_t data[][8]
is supposed to be an array of arbitrary height and a maximum width of 8 but possibly smaller.
I've tried to use templates but realized that this would result in bigger problems in other parts of the code. If I were to use templates, then they could only be used in the constructor without having to do something like LEDBitmap<5, 5> image = ...
but rather just using LEDBitmap image = LEDBitmap<5, 5>(...)
I am unable to use vectors since they are not part of the Arduino IDE, which is written in C. I have my library in C++ because I am using some other libraries which are in C++ and originally wanted to use a different platform but due to some issues with that I had to switch to Arduino recently.
The error I'm currently getting is: no known conversion for argument 3 from 'uint8_t [3][3] {aka unsigned char [3][3]}' to 'uint8_t (*)[8] {aka unsigned char (*)[8]}'
Thanks in advance for your tips and help.
Upvotes: 0
Views: 79
Reputation: 149075
C++ does not like variable length arrays (never defined in standard even if supported in some implementations) nor raw 2D arrays. If you do not require true []
operator support, my advice is to use accessor functions:
class Array2D {
size_t width, height;
uint8_t *data;
public:
Array2D(size_t width, size_t height): width(width), height(height() {
data = new uint8_t[width * height];
}
~Arrayt2D() {
delete[] data;
}
// copy/move ctor-assignment operator omitted for brievety but REQUIRED (law of three/five)
uint8_t getVal(size_t i, size_t j) const {
return data[i + j * width];
}
uint8_t setVal(uint8_t val, size_t i, size_t j) {
data[i + j * width] = val;
}
/* alternatively to use arr.val(i, j) = value :
uint8_t& val(size_t i, size_t j) {
return data[i + j * width];
}
*/
// other accessors (height, width) omitted but probably useful...
};
Rather C-ish, but as you cannot use vectors and prefer to avoid templates, it could be a basic skeleton...
Upvotes: 1