Hello all
I'm trying to implement a template class for dynamic 2D arrays for my arduino project.
I'm using Aruino IDE 1.8.19 with default settings.
Target board - Arduino Nano V3.
Problemm summary: Code compiles, but works correctly only for byte and int types, and doesnt work for double and unsigned long types (even though I'm using "template <typename T>" statements).
I'm guess there is some problemm with double pointer indexing/pointer arythmetics,
but I have no idea how to solve it. I will very appreciate if somebody can check it.
Detailed problemm description (expected vs actual output) is in comments in my code below.
".ino" file - detailed problemm description is here
#include "Dynamic2DArr.h"
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
// Create 4-rows 3-cols 2D array for doubles
// (Default values will be "7")
Dynamic2DArr<double> dynX(4, 3);
// Debugger serial output from constructor - as expected:
// Why it is as expected here, but not es expected later??
// "Arr[0][0]=7.00;Arr[0][1]=7.00;Arr[0][2]=7.00;
// Arr[1][0]=7.00;Arr[1][1]=7.00;Arr[1][2]=7.00;
// Arr[2][0]=7.00;Arr[2][1]=7.00;Arr[2][2]=7.00;
// Arr[3][0]=7.00;Arr[3][1]=7.00;Arr[3][2]=7.00;"
// display array using indexing
dynX.dispArr();
// PROBLEM:
// Expected serial output:
// "Dynamic2DAr::dispArr() start
// 7.00; 7.00; 7.00;
// 7.00; 7.00; 7.00;
// 7.00; 7.00; 7.00;
// 7.00; 7.00; 7.00;
// Dynamic2DAr::dispArr() end"
// Actual serial output:
// "Dynamic2DAr::dispArr() start
// 7.00; 0.00; 0.00;
// 7.00; 0.00; 0.00;
// 7.00; 0.00; 0.00;
// 7.00; 7.00; 7.00;
// Dynamic2DAr::dispArr() end"
// display array using getters and setters
check2DArr(dynX);
// PROBLEM:
// Expected serial output:
// "FUNCTION check2D()
// 7.00; 7.00; 7.00;
// 7.00; 7.00; 7.00;
// 7.00; 7.00; 7.00;
// 7.00; 7.00; 7.00;
// Actual serial output:
// "FUNCTION check2D()
// 7.00; 0.00; 0.00;
// 7.00; 0.00; 0.00;
// 7.00; 0.00; 0.00;
// 7.00; 7.00; 7.00;
// Fill array with data
dynX.setVal(0, 0, 11); dynX.setVal(0, 1, 12); dynX.setVal(0, 2, 13);
dynX.setVal(1, 0, 21); dynX.setVal(1, 1, 22); dynX.setVal(1, 2, 23);
dynX.setVal(2, 0, 31); dynX.setVal(2, 1, 32); dynX.setVal(2, 2, 33);
dynX.setVal(3, 0, 41); dynX.setVal(3, 1, 42); dynX.setVal(3, 2, 43);
// display array using indexing
dynX.dispArr();
// PROBLEM:
// Expected serial output:
// "Dynamic2DAr::dispArr() start
// 11.00; 12.00; 13.00;
// 21.00; 22.00; 23.00;
// 31.00; 32.00; 33.00;
// 41.00; 42.00; 43.00;
// Dynamic2DAr::dispArr() end"
// Actual serial output:
// "Dynamic2DAr::dispArr() start
// 11.00; 0.00; 0.00;
// 21.00; 0.00; 0.00;
// 31.00; 0.00; 0.00;
// 41.00; 42.00; 43.00;
// Dynamic2DAr::dispArr() end"
// display array using getters and setters
check2DArr(dynX);
// PROBLEM:
// Expected serial output:
// "Dynamic2DAr::dispArr() start
// 11.00; 12.00; 13.00;
// 21.00; 22.00; 23.00;
// 31.00; 32.00; 33.00;
// 41.00; 42.00; 43.00;
// Dynamic2DAr::dispArr() end"
// Actual serial output:
// "Dynamic2DAr::dispArr() start
// 11.00; 0.00; 0.00;
// 21.00; 0.00; 0.00;
// 31.00; 0.00; 0.00;
// 41.00; 42.00; 43.00;
// Dynamic2DAr::dispArr() end"
}
void loop() {
// put your main code here, to run repeatedly:
}
template <typename T>
void check2DArr(Dynamic2DArr<T> &dynArr)
{
Serial.println(F("FUNCTION check2D()"));
int rows = dynArr.getRowsCnt();
int cols = dynArr.getColsCnt();
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
Serial.print(dynArr.getVal(i,j));
Serial.print(F("; "));
}
Serial.println();
}
}
".h" file
#ifndef DYNAMIC2DARR_H
#define DYNAMIC2DARR_H
#include <Arduino.h>
#define DEBUG_MODE
template <typename T>
class Dynamic2DArr
{
private:
int rows_cnt;
int cols_cnt;
T** Arr;
public:
Dynamic2DArr(int rows_cnt, int cols_cnt);
~Dynamic2DArr();
int getRowsCnt();
int getColsCnt();
void setVal(int row_idx, int col_idx, T val);
T getVal(int row_idx, int col_idx);
T** getArrPtr();
void dispArr();
};
template <typename T>
Dynamic2DArr<T>::Dynamic2DArr(int rows_cnt, int cols_cnt)
{
#ifdef DEBUG_MODE
Serial.println(F("Constructor Dynamic2DAr::Dynamic2DArr() start"));
#endif
this->rows_cnt = rows_cnt;
this->cols_cnt = cols_cnt;
this->Arr = new T*[rows_cnt];
for(int row = 0; row < this->rows_cnt; row++)
{
this->Arr[row] = new T(this->cols_cnt);
#ifdef DEBUG_MODE
Serial.print(F("row # "));
Serial.print(row);
Serial.print(F(" columns added "));
Serial.println(this->cols_cnt);
#endif
}
for(int row = 0; row < this->rows_cnt; row++)
{
for(int col = 0; col < this->cols_cnt; col++)
{
this->Arr[row][col] = 7;
#ifdef DEBUG_MODE
Serial.print(F("Arr["));
Serial.print(row);
Serial.print(F("]["));
Serial.print(col);
Serial.print(F("]="));
Serial.print(this->Arr[row][col]);
Serial.print(F(";"));
#endif
}
#ifdef DEBUG_MODE
Serial.println();
#endif
}
#ifdef DEBUG_MODE
Serial.println(F("Constructor Dynamic2DAr::Dynamic2DArr() end"));
#endif
}
template <typename T>
Dynamic2DArr<T>::~Dynamic2DArr()
{
#ifdef DEBUG_MODE
Serial.println(F("Destructor Dynamic2DAr::~Dynamic2DArr() start"));
#endif
for(int row = 0; row < rows_cnt; row++)
{
delete[] this->Arr[row];
}
delete[] this->Arr;
this->Arr = NULL;
#ifdef DEBUG_MODE
Serial.println(F("Destructor Dynamic2DAr::~Dynamic2DArr() end"));
#endif
}
template <typename T>
int Dynamic2DArr<T>::getRowsCnt()
{
return rows_cnt;
}
template <typename T>
int Dynamic2DArr<T>::getColsCnt()
{
return cols_cnt;
}
template <typename T>
void Dynamic2DArr<T>::setVal(int row_idx, int col_idx, T val)
{
this->Arr[row_idx][col_idx] = val;
#ifdef DEBUG_MODE
Serial.print(F("Dynamic2DAr::setVal() Arr["));
Serial.print(row_idx);
Serial.print(F("]["));
Serial.print(col_idx);
Serial.print(F("]="));
Serial.print(Arr[row_idx][col_idx]);
Serial.println(F(" Done;"));
#endif
}
template <typename T>
T Dynamic2DArr<T>::getVal(int row_idx, int col_idx)
{
return this->Arr[row_idx][col_idx];
}
template <typename T>
T** Dynamic2DArr<T>::getArrPtr()
{
return this->Arr;
}
template <typename T>
void Dynamic2DArr<T>::dispArr()
{
#ifdef DEBUG_MODE
Serial.println(F("Dynamic2DAr::dispArr() start"));
for(int row = 0; row < this->rows_cnt; row++)
{
for(int col = 0; col < this->cols_cnt; col++)
{
Serial.print(this->Arr[row][col]);
Serial.print(F("; "));
}
Serial.println();
}
Serial.println(F("Dynamic2DAr::dispArr() end"));
#endif
}
#endif
".cpp" file
#include "Dynamic2DArr.h"
// By some reason can compiller throws error when
// template functions declarations and definitions are
// separated in .h and .cpp file
// all template functions definitiona are in .h file