How to use a class in another class in Arduino C++ (FastLED)? - c++

I am working on an ledstip project for my room. I am using arduino to do this. For this project i want to use C++ so i can use OOP. After i got my ledstrips working I wanted to create a cluster class that used the strip class to control a specific piece of the LED strip. I can't get this to work. The compiler gives no errors and I see no change after using the function Desk.rgb(0,100,0);.
Here is my .h file
#include <FastLED.h>
template<class T>
class Cluster {
public:
T Strip;
int first;
int last;
Cluster(T Strip, int first, int last) {
this->Strip = Strip;
this->first = first;
this->last = last;
}
void rgb(int r, int g, int b){
Strip.rgb( r, g, b, first, last);
}
};
template<byte pin, int AmountOfLeds>
class Strip {
public:
CRGB leds[AmountOfLeds];
void setup() {
FastLED.addLeds<WS2812, pin, GRB>(leds, AmountOfLeds);
rgb(0, 0, 0);
}
//hole strip
void rgb(int r, int g, int b) {
for (int i = 0; i <= AmountOfLeds - 1; i++) {
this->leds[i] = CRGB(r, g, b);
}
FastLED.show();
}
//single led
void rgb(int i, int r, int g, int b) {
this->leds[i] = CRGB(r, g, b);
FastLED.show();
}
//range
void rgb(int r, int g, int b, int f, int l) {
for (int i = f; i <= l; i++) {
this->leds[i] = CRGB(r, g, b);
}
FastLED.show();
}
void hsv(int h, int s, int v) {
for (int i = 0; i <= AmountOfLeds; i++) {
this->leds[i] = CHSV(h, s, v);
}
FastLED.show();
}
void hsv(int i, int h, int s, int v) {
this->leds[i] = CHSV(h, s, v);
FastLED.show();
}
void hsv(int h, int s, int v, int f, int l) {
for (int i = f; i <= l; i++) {
this->leds[i] = CHSV(h, s, v);
}
FastLED.show();
}
void hsvWhiteBalance(int S, int V) { //S is yellowness, V is brightness
hsv(15, S, V);
}
void rainbow(float V) {
for (int i = 0; i <= AmountOfLeds; i++) {
leds[i] = CHSV( float(i) * (255 / float(AmountOfLeds)), 255, V);
}
FastLED.show();
}
void rainbow(float p, float V) {
for (int i = 0; i <= AmountOfLeds; i++) {
leds[i] = CHSV( float(i) * (255.0 / float(AmountOfLeds) * p), 255, V);
}
FastLED.show();
}
};
This is my .ino file:
#include "LedClasses.h"
Strip<5, 190> DTVC;
Cluster<Strip<5, 190>> Desk(DTVC, 1, 42);
void setup() {
Serial.begin(9600);
DTVC.setup();
DTVC.hsvWhiteBalance(153, 50);
Desk.rgb(0,100,0);
//DTVC.rgb(Desk, 0, 100, 0);
}
Thanks in advance.

Doesn't work, because in the Cluster constructor you take Strip class by copy. Then, in your example you have 2 instances of Stripe: one in the global context, and one inside the Cluster. You invoke Stripe::setup (which calls FastLED.addLeds) on the instance in the global context (registering the address of the Stripe::ledspublic field in the FastLED library), but later you call rgb on the instance that lives inside your Cluster and has different Stripe::leds field.
To fix it quickly (not very clean, though), you can redesign your constructor to accept a reference instead of copy:
class Cluster {
public:
T& strip;
int first;
int last;
Cluster(T& s, int f, int l): strip(s), first(f), last(l) {}
Alternatively, you can redesign your architecture a bit more, to not use the templates so much (you can play with constexpr arguments instead).

Related

Segment tree with lazy propagation doesn't work

I am trying to implement a segment tree with lazy propagation. The queries I need are:
sum of elements in range [a,b)
elements in range [a, b) become equal to x
add x to elements in range [a,b)
I wrote some code, but it does not work.
a and b goes from 0 to N-1, while the segment tree is 1-indexed
The function add must add x to elements from l (included) to r (not included)
The function add must make elements from l (included) to r (not included) become x.
When one of the above functions meet a node which range is completely inside l and r, then it sets is lazyadd or lazyset to the value to be added to those elements.
Whenever a function meet a node, it checks if it has any lazy update to do, through the functions uplset and upladd, that update the node and change the lazy value of their children.
#include <iostream>
#include <vector>
#include <limits.h>
using namespace std;
struct Node {
long long sum;
long long min;
long long lazyset;
long long lazyadd;
Node() : sum(0), min(INT_MAX), lazyset(0), lazyadd(0) {};
};
vector<Node> tree;
int reals=1; // size of the tree
void init(vector<long long> a) { // build segment tree from vector a
int size = a.size();
while(reals<a.size()) {
reals*=2;
}
tree.resize(2*reals);
for(int i=0;i<a.size();i++) {
tree[reals+i].min=a[i];
tree[reals+i].sum=a[i];
}
for(int i=reals-1;i>0;i--) {
tree[i].sum=tree[2*i].sum+tree[2*i+1].sum;
tree[i].min=min(tree[2*i].min, tree[2*i+1].min);
}
}
void uplset(int k, int x, int y, long long rx) { // lazy set update
int d = y-x;
int lazy = tree[k].lazyset;
tree[k].sum=d*rx;
if(k<reals) {
tree[k*2].lazyset=lazy;
tree[k*2+1].lazyset=lazy;
}
tree[k].lazyset=0;
}
void upladd(int k, int x, int y, long long rx) { // lazy add update
int d = y-x;
int lazy = tree[k].lazyadd;
tree[k].sum+=d*rx;
if(k<reals) {
tree[k*2].lazyadd=lazy;
tree[k*2+1].lazyadd=lazy;
}
tree[k].lazyadd=0;
}
long long rsum(int a, int b, int k, int x, int y) { // sum of elements
if(tree[k].lazyadd!=0) {
upladd(k,x,y,tree[k].lazyadd);
}
if(tree[k].lazyset!=0) {
uplset(k,x,y,tree[k].lazyset);
}
if(b<=x||a>=y) return 0;
if(a<=x&&b>=y) return tree[k].sum;
int d = (x+y)/2;
return rsum(a, b, 2*k, x, d) + rsum(a, b, 2*k+1, d, y);
}
long long get_sum(int l, int r) {
return rsum(l, r, 1, 0, reals);
}
void rladd(int a, int b, int k, int x, int y, long long rx) { // add rx to elements
if(tree[k].lazyadd!=0) {
upladd(k,x,y,tree[k].lazyadd);
}
if(tree[k].lazyset!=0) {
uplset(k,x,y,tree[k].lazyset);
}
if(y<=a||x>=b) return;
if(x>=a&&y<=b) {
tree[k].lazyadd=rx;
} else {
int d=(x+y)/2;
rladd(a,b,2*k,x, d,rx);
rladd(a,b,2*k+1,d, y,rx);
long long uno = tree[k*2].lazyadd ? tree[k*2].sum+tree[k*2].lazyadd*(d-x) : tree[k*2].sum;
long long due = tree[k*2+1].lazyadd ? tree[k*2].sum+tree[k*2+1].lazyadd*(d-x) : tree[k*2+1].sum;
tree[k].sum=uno+due;
}
}
void add(int l, int r, long long x) {
return rladd(l,r,1,0,reals, x);
}
void rlset(int a, int b, int k, int x, int y, long long rx) {
if(tree[k].lazyadd!=0) {
upladd(k,x,y,tree[k].lazyadd);
}
if(tree[k].lazyset!=0) {
uplset(k,x,y,tree[k].lazyset);
}
if(y<=a||x>=b) return;
if(x>=a&&y<=b) {
tree[k].lazyset=rx;
} else {
int d=(x+y)/2;
rlset(a,b,2*k,x, d,rx);
rlset(a,b,2*k+1,d, y,rx);
long long uno = tree[k*2].lazyset ? tree[k*2].lazyset*(d-x) : tree[k*2].sum;
long long due = tree[k*2+1].lazyset ? tree[k*2+1].lazyset*(d-x) : tree[k*2+1].sum;
tree[k].sum=uno+due;
}
}
void set_range(int l, int r, long long x) {
rlset(l,r,1,0,reals,x);
}

Unable to read memory for object array deletion

So I am testing out some object arrays in C++, and I am trying to delete these objects afterwards, as I am supposed to.
But here's the problem: the deleteInputPattern variable works fine, so I am able to fully delete "inputs" within the CSVFile header class, but its equivalent in the main file, "inputArray", triggers a breakpoint.
What is the problem here? Am I trying to delete non-existent memory? Do any of the pointers need
Code wall below:
InputTest.h:
#pragma once
class InputTest
{
private:
float r;
float g;
float b;
float t;
public:
InputTest();
~InputTest();
InputTest(float r, float g, float b, float t);
void setR(float newT);
float getR();
void setG(float newT);
float getG();
void setB(float newT);
float getB();
void setT(float newT);
float getT();
void print(int count);
};
InputTest.cpp:
#include "InputTest.h"
#include <stdio.h>
InputTest::InputTest()
{
printf("Input constructor\n");
}
InputTest::~InputTest()
{
printf("Input destructor\n");
}
InputTest::InputTest(float r, float g, float b, float t)
{
this->r = r;
this->g = g;
this->b = b;
this->t = t;
}
void InputTest::setR(float newT)
{
r = newT;
}
float InputTest::getR()
{
return r;
}
void InputTest::setG(float newT)
{
g = newT;
}
float InputTest::getG()
{
return g;
}
void InputTest::setB(float newT)
{
b = newT;
}
float InputTest::getB()
{
return b;
}
void InputTest::setT(float newT)
{
t = newT;
}
float InputTest::getT()
{
return t;
}
void InputTest::print(int count)
{
printf("R: %.2f\n", r);
printf("G: %.2f\n", g);
printf("B: %.2f\n", b);
printf("T: %.2f\n", t);
}
Copy.h:
#pragma once
class InputTest;
class Copy
{
private:
int patternCount;
InputTest** inputs;
public:
Copy();
~Copy();
InputTest* getInputPattern(int index);
void addInputPattern(InputTest* in);
void deleteInputPattern();
};
Copy.cpp:
#include "Copy.h"
#include "InputTest.h"
#include <string.h>
#include <stdio.h>
Copy::Copy()
{
printf("CSV File constructor\n");
inputs = NULL;
patternCount = 0;
inputs = new InputTest*[3];
int i;
for (i = 0; i < 3; i++)
{
inputs[i] = new InputTest();
}
}
Copy::~Copy()
{
printf("CSV File destructor\n");
}
InputTest * Copy::getInputPattern(int index)
{
printf("input gotten: %d\n", index);
return inputs[index];
}
void Copy::addInputPattern(InputTest * in)
{
inputs[patternCount] = in;
patternCount++;
printf("input added: %d\n", patternCount);
}
void Copy::deleteInputPattern()
{
int i;
for (i = 0; i < patternCount; i++)
{
delete inputs[i];
}
delete inputs;
inputs = NULL;
}
main.cpp:
#include "Copy.h"
#include "InputTest.h"
#include <string.h>
#include <stdio.h>
int main(int argv, char** argc)
{
bool testResult = false;
Copy *test = NULL;
test = new Copy();
InputTest **inputArray;
inputArray = new InputTest*[3];
int count;
for (count = 0; count < 3; count++)
{
inputArray[count] = new InputTest();
inputArray[count]->setR(0.2f);
inputArray[count]->setG(0.6f);
inputArray[count]->setB(0.8f);
inputArray[count]->setT(0.5f);
test->addInputPattern(inputArray[count]);
inputArray[count] = test->getInputPattern(count);
printf("next\n");
}
for (count = 0; count < 3; count++)
{
printf("round %d\n", count);
printf("R: %f\n", inputArray[count]->getR());
printf("G: %f\n", inputArray[count]->getG());
printf("B: %f\n", inputArray[count]->getB());
printf("T: %f\n", inputArray[count]->getT());
}
test->deleteInputPattern();
for (count = 0; count < 3; count++)
{
delete inputArray[count];
}
delete inputArray;
delete test;
inputArray = NULL;
test = NULL;
return testResult;
}
These seem to be the problematic line:
test->deleteInputPattern();
for (count = 0; count < 3; count++)
{
delete inputArray[count];
}
Since you have already deleted using test->deleteInputPattern(), that memory is freed. Now you are deleting the same objects (to which you are still holding a reference via inputArray) explicitly in main using delete inputArray. But that memory is already deleted in deleteInputPattern and hence you should be getting a memory access error.
You need to free any allocated memory only once. There is no need to do it again in main(). Either call deleteInputPattern or call delete explicitly in main, but not both. I can recommend 2 best practices:
Use smart pointers
The allocating module should delete the memory (this may not be applicable in many situations though such as factories)

How to sort an object array

I've created a class called Box that is pretty much what it sounds like. I want to sort these box objects, and I have created a function to do so.
void boxSort(Box array[], int size) {
Box temp;
bool swap;
do {
swap = false;
for(int count=0; count<(size-1); count++) {
int volume1 = array[count].getVolume(array[count].height, array[count].width, array[count].length);
int volume2 = array[count+1].getVolume(array[count+1].height, array[count+1].width, array[count+1].length);
if(volume1 > volume2) {
temp = array[count];
array[count] = array[count+1];
array[count+1] = temp;
swap = true;
}
}
}
while(swap);
}
This function sorts an array of objects of class Box.
Box class:
class Box {
public:
double height, width, length;
double getVolume(double, double, double);
double getSurfaceArea(double, double, double);
void setHeight(double);
void setWidth(double);
void setLength(double);
Box() {
height = width = length = 1;
}
Box(double h, double w, double l) {
setHeight(h);
setWidth(w);
setLength(l);
}
};
#endif
void Box::setHeight(double h) {
height = h;
}
void Box::setWidth(double w) {
width = w;
}
void Box::setLength(double l) {
length = l;
}
double Box::getVolume(double h, double w, double l) {
double volume = h*w*l;
return volume;
}
double Box::getSurfaceArea(double h, double w, double l) {
double surfaceArea = (h*w)*2 + (h*l)*2 + (l*w)*2;
return surfaceArea;
}
When I run this program I get an error:
linker command failed with exit code 1
This doesn't shown up on any particular line, and I have no idea what it means, so I'm a little lost on how to debug this.
The linker errors are reported if you have any problem with libraries or object files linked. Were you able to successfully build the executable?
I think this error is occurring due to more than one main() function in your code.You can have only one main() function.
Not sure about the error. But I would suggest changing boxSort function to something like this.
change getVolume to this
double Box::getVolume() {
return height*width*length;
}
and boxSort to this
void boxSort(std::array<Box, 3> boxes)
{
struct
{
bool operator()(Box x, Box y)
{
return x.getVolume() < y.getVolume();
}
}compFunc;
std::sort(boxes.begin(), boxes.end(), compFunc);
for(Box a: boxes)
{
std::cout<<a.getVolume()<<" ";
}
}
function call:
std::array<Box,3> boxes = {box1, box2, box3};
boxSort(boxes);

Use push_back() to add an item in a vector, the size of the vector increase but can't read values from the vector

I have a class ColorName, and a class ColorNameLookup. In class ColorNameLookup, there is a public member: vector colorList. And the constructor of class ColorNameLookup is to add items into the vector colorList.
I add 140 items into the vector colorList. I checked the size of the vector is correct, but I can't read any value from the vector.
For instance, I initialize a variable ColorNameLookup findColor, and use function findColor.colorList[0].getR() to get the first element's R value. The return is an uninitialized integer value.
my code is shown below:
Class ColorName:
#include "ColorName.h"
ColorName::ColorName(std::string name, int r, int g, int b)
{
r = r;
g = g;
b = b;
name = name;
}
ColorName::ColorName(void)
{
}
ColorName::~ColorName(void)
{
}
int ColorName::computeMSE(int pixR, int pixG, int pixB) {
return ((pixR-r)*(pixR-r) + (pixG-g)*(pixG-g) + (pixB-b)*(pixB-b)/3);
}
int ColorName::getR() {
return r;
}
int ColorName::getG() {
return g;
}
int ColorName::getB() {
return b;
}
std::string ColorName::getName() {
return name;
}
Class ColorNameLookup:
ColorNameLookup::ColorNameLookup(void)
{
colorList.push_back(ColorName("AliceBlue",0xF0,0xF8,0xFF));
//...139 push_back
colorList.push_back(ColorName("YellowGreen",0x9A,0xCD,0x32));
}
ColorNameLookup::~ColorNameLookup(void)
{
}
std::string ColorNameLookup::getColorName(int r, int g, int b) {
ColorName closestMatch; // = NULL;
int findFlag = 0;
int minMSE = std::numeric_limits<int>::max();
int mse;
for (ColorName c : colorList) {
mse = c.computeMSE(r, g, b);
if (mse < minMSE) {
findFlag = 1;
minMSE = mse;
closestMatch = c;
//printf("Find color!\n");
}
}
if (findFlag ==1){
return closestMatch.getName();
}
else
return NULL;
}
You'd need this:
ColorName::ColorName(std::string name, int r, int g, int b)
{
this->r = r;
this->g = g;
this->b = b;
this->name = name;
}
r = r would just assign the same local r to itself, and leave the member variables uninitialized.
For initializing these members, you'd be better off with an initializer list though:
ColorName::ColorName(std::string name, int r, int g, int b) :
r(r),
g(g),
b(b),
name(name)
{
}

C++ : Can't pass generic function to another one as a parameter

I want to pass multiple compare functions to the selection sort function as shown below but i get the fallowing error :
Error 1 error C2664: 'sort' : cannot convert parameter 3 from 'bool (__cdecl *)(int,int)' to 'bool *(__cdecl *)(T,T)' c:\users\milad\documents\visual studio 2008\projects\functionpass\functionpass\passcompare.cpp 49 FunctionPass
Code :
bool integerCompare (int a , int b)
{
return(a<b);
}
bool charCompare (char a , char b)
{
return(a<b);
}
bool stringCompare (string a , string b)
{
if(a.compare(b)<0) return true;
else return false;
}
template <class T>
void sort(T x[], int n , bool(*whichCompare(T,T))) // n=size of the array
{
for (int pass=0; pass<n-1; pass++) {
int potentialSmallest = pass;
for (int i=pass+1; i<n; i++) {
if ((*whichCompare)(x[i],x[potentialSmallest])) {
potentialSmallest = i;
}
}
int temp = x[pass];
x[pass] = x[potentialSmallest];
x[potentialSmallest] = temp;
}
}
template <typename T>
void printArray(T a[], int size)
{
for(int i=0;i<size;i++)
cout<<" "<<a[i];
}
int main()
{
int intArray[] = {1,7,-8,-14,46,33,4};
sort <int>(intArray , 7 , integerCompare);
printArray<int>(intArray,7);
}
You have this:
template <class T> void sort(T x[], int n , bool(*whichCompare(T,T)))
{ /*...*/ }
The parameter declaration for a pointer to a function returning a bool and two arguments of type T is wrong. You probably really wanted:
template <class T> void sort(T x[], int n , bool (*whichCompare)(T,T))
{ /*...*/ }
Although typically functions like these are written like this:
template <class T, typename Functor>
void sort(T x[], int n , Functor whichCompare)
{
// ...
bool result = whichCompare(x[i], x[potentialSmallest]);
// ...
}
This way, users can not only pass in function pointers, but function objects that provides an operator()():
struct MyIntegerCompareFunctor
{
bool operator()(int a, int b) { return a < b; }
};
sort(intArray, 7, MyIntegerCompareFunctor());
sort(intArray, 7, &integerCompare); // Works too
Some of the algorithms provided by the C++ standard libraries are written like this.
See my corrections in the lines that have whichCompare in them.
template <class T>
void sort(T x[], int n , bool(*whichCompare)(T,T)) // n=size of the array
{
for (int pass=0; pass<n-1; pass++) {
int potentialSmallest = pass;
for (int i=pass+1; i<n; i++) {
if (whichCompare(x[i],x[potentialSmallest])) {
potentialSmallest = i;
}
}
int temp = x[pass];
x[pass] = x[potentialSmallest];
x[potentialSmallest] = temp;
}
}
You could also templatise the function itself thus:
template< typename T, typename Pred >
void sort( T x[], int n, Pred whichCompare )
{ // etc.
}
I used to do this initially just because it was easier but also allows functors / boost-function/boost-bind etc. to be used with your algorithm.
there is a much more sexy solution:
bool integerCompare (int a , int b)
{
return(a<b);
}
bool charCompare (char a , char b)
{
return(a<b);
}
bool stringCompare (string a , string b)
{
return (a.compare(b)<0);
}
template <typename T, size_t n >
void sort(T (&x)[n], bool whichCompare (T,T) ) // n=size of the array
{
for (int pass=0; pass<n-1; pass++) {
int potentialSmallest = pass;
for (int i=pass+1; i<n; i++) {
if (whichCompare(x[i],x[potentialSmallest])) {
potentialSmallest = i;
}
}
std::swap(x[pass], x[potentialSmallest]);
}
}
template <typename T, size_t n>
void printArray(T (&a)[n])
{
for(int i=0;i<n;i++)
cout<<" "<<a[i];
}
int main()
{
int intArray[] = {1,7,-8,-14,46,33,4};
sort (intArray, integerCompare);
printArray(intArray);
}