Large static arrays in header only implementation - c++

Due to the need to be able to reference unicode character groups in a header only implementation, I want to declare all the arrays first. Templates allow me to initialize static members in the header, but the code looks messy.
This is just two of the twenty or so groups:
struct CharacterClass
{
struct Value
{
int l;
int h;
};
};
template < int N >
struct Nd : public CharacterClass
{
static const Value v[];
};
template< int N >
const typename Nd< N >::Value Nd< N >::v[] = {
{ 0x00030 , 0x00039 }, { 0x00660 , 0x00669 }, { 0x006f0 , 0x006f9 }, { 0x007c0 , 0x007c9 }, { 0x00966 , 0x0096f },
{ 0x009e6 , 0x009ef }, { 0x00a66 , 0x00a6f }, { 0x00ae6 , 0x00aef }, { 0x00b66 , 0x00b6f }, { 0x00be6 , 0x00bef },
{ 0x00c66 , 0x00c6f }, { 0x00ce6 , 0x00cef }, { 0x00d66 , 0x00d6f }, { 0x00e50 , 0x00e59 }, { 0x00ed0 , 0x00ed9 },
{ 0x00f20 , 0x00f29 }, { 0x01040 , 0x01049 }, { 0x017e0 , 0x017e9 }, { 0x01810 , 0x01819 }, { 0x01946 , 0x0194f },
{ 0x019d0 , 0x019d9 }, { 0x01b50 , 0x01b59 }, { 0x0ff10 , 0x0ff19 }
};
template < int N >
struct Nl : public CharacterClass
{
static const Value v[];
};
template< int N >
const typename Nl< N >::Value Nl< N >::v[] = {
{ 0x016ee , 0x016f0 }, { 0x02160 , 0x02182 }, { 0x03007, 0x03007 }, { 0x03021 , 0x03029}, { 0x03038 , 0x0303a }
};
Q1: Is it possible to declare the array once in a base class without having to repeat it for each derived type?
Q2: How can I hide the dummy 'int N', so that I can later reference the structs without having to add the template parameter? ie. int x = Nd.v[10].l;
Q3: Is there a better way of doing this?

I will try to give you an alternative for Q1 you've asked.
I don't like to see hard-coded values which are meaningless to the program logics.
Here's a nice trick That I use sometimes:
Create a new file and paste the values in it.
data.dat
{ 0x00030 , 0x00039 }, { 0x00660 , 0x00669 }, { 0x006f0 , 0x006f9 }, { 0x007c0 , 0x007c9 }, { 0x00966 , 0x0096f },
{ 0x009e6 , 0x009ef }, { 0x00a66 , 0x00a6f }, { 0x00ae6 , 0x00aef }, { 0x00b66 , 0x00b6f }, { 0x00be6 , 0x00bef },
{ 0x00c66 , 0x00c6f }, { 0x00ce6 , 0x00cef }, { 0x00d66 , 0x00d6f }, { 0x00e50 , 0x00e59 }, { 0x00ed0 , 0x00ed9 },
{ 0x00f20 , 0x00f29 }, { 0x01040 , 0x01049 }, { 0x017e0 , 0x017e9 }, { 0x01810 , 0x01819 }, { 0x01946 , 0x0194f },
{ 0x019d0 , 0x019d9 }, { 0x01b50 , 0x01b59 }, { 0x0ff10 , 0x0ff19 }
now, when you want to repeat it, do the following:
const typename Nd< N >::Value Nd< N >::v[] = {
#include "data.dat"
};
This way, the preprocessor will paste all this values for you, so you don't need to repeat them all the time.

Answering my own questions. I placed the whole combined array in a base class, then derived from that with derived types initializing themselves to an index within the array.
struct CharacterClass
{
struct Value
{
int l;
int h;
};
};
template < int X >
struct Base : public CharacterClass
{
static const Value v[];
};
template< int X >
const typename Base< X >::Value Base< X >::v[] = {
// Nd values length 23 index 0
{ 0x00030 , 0x00039 }, { 0x00660 , 0x00669 }, { 0x006f0 , 0x006f9 }, { 0x007c0 , 0x007c9 }, { 0x00966 , 0x0096f },
{ 0x009e6 , 0x009ef }, { 0x00a66 , 0x00a6f }, { 0x00ae6 , 0x00aef }, { 0x00b66 , 0x00b6f }, { 0x00be6 , 0x00bef },
{ 0x00c66 , 0x00c6f }, { 0x00ce6 , 0x00cef }, { 0x00d66 , 0x00d6f }, { 0x00e50 , 0x00e59 }, { 0x00ed0 , 0x00ed9 },
{ 0x00f20 , 0x00f29 }, { 0x01040 , 0x01049 }, { 0x017e0 , 0x017e9 }, { 0x01810 , 0x01819 }, { 0x01946 , 0x0194f },
{ 0x019d0 , 0x019d9 }, { 0x01b50 , 0x01b59 }, { 0x0ff10 , 0x0ff19 },
// Nl values length 5 index 23
{ 0x016ee , 0x016f0 }, { 0x02160 , 0x02182 }, { 0x03007, 0x03007 }, { 0x03021 , 0x03029}, { 0x03038 , 0x0303a }
};
template < int _index, int _length >
struct BaseIndex : public Base< 0 >
{
static const Value * v;
static const int length;
};
template < int _index, int _length >
const typename BaseIndex< _index, _length >::Value * BaseIndex< _index, _length >::v = &Base::v[ _index ];
template < int _index, int _length >
const int BaseIndex< _index, _length >::length = _length;
struct Nd : public BaseIndex< 0, 23 >
{
};
struct Nl : public BaseIndex< 23, 5 >
{
};
I think just a typedef in the namespace can replace those struct's Nd and Nl.
If there's a better way, I'm still open to suggestions.

Related

Use attribute from derived class while using method from the base class?

I have the following code:
#include <map>
class vehicle {
private:
int id = 0;
std::map<std::pair<int, char>, int> seats{};
public:
void displaySeats();
};
class Bus : public vehicle {
private:
std::string type = "Bus";
public:
std::map<std::pair<int, char>, int> seats{ {{1,'A'},0 }, {{1,'B'},0 }, {{ 1,'C' }, 0}, {{ 1,'D' }, 0 }, {{ 1,'E' }, 0 },
{{2,'A'},0 }, {{2,'B'},0 }, {{ 2,'C' }, 0}, {{ 2,'D' }, 0 }, {{ 2,'E' }, 0 },
{{3,'A'},0 }, {{3,'B'},0 }, {{ 3,'C' }, 0}, {{ 3,'D' }, 0 }, {{ 3,'E' }, 0 },
{{4,'A'},0 }, {{4,'B'},0 }, {{ 4,'C' }, 0}, {{ 4,'D' }, 0 }, {{ 4,'E' }, 0 },
{{5,'A'},0 }, {{5,'B'},0 }, {{ 5,'C' }, 0}, {{ 5,'D' }, 0 }, {{ 5,'E' }, 0 }};
};
class MiniVan : public vehicle {
private:
std::string type = "MiniVan";
public:
// Seats map. <int, char> represents seats id(1A 1B 1C) the <int> will be either 0 or 1, representing if the seat is taken(1) or free(0).
std::map<std::pair<int, char>, int> seats{ {{1,'A'},0 }, {{1,'B'},0 }, {{ 1,'C' }, 0},
{{2,'A'},0 }, {{2,'B'},0 }, {{ 2,'C' }, 0},
{{3,'A'},0 }, {{3,'B'},0 }, {{ 3,'C' }, 0},
{{4,'A'},0 }, {{4,'B'},0 }, {{ 4,'C' }, 0} };
};
void vehicle::displaySeats()
{
std::pair<int, char> seat{ 1, 'E'};
int columns = 5?this->seats.count(seat)>0:3;
int displayRow = 0;
for (const auto& p : this->seats) {
if (displayRow == columns) {
std::cout << std::endl;
displayRow = 0;
}
displayRow++;
std::cout << p.first.first << p.first.second << "\t ";
}
};
In main() i have:
MiniVan testMiniVan;
testMiniVan.displaySeats();
It displays the empty seats map attribute from the base class.
I am new to c++, but in other languages, it takes the derived class attribute. How can I solve this problem? Will I have to create displaySeats for each child class ? If yes, then why do I need base class in the first place?
This is something I've done fairly often as well, the issue is how things are constructed and which functions have access to which variables. Maybe you could do something like:
class Vehicle {
private:
int id = 0;
std::map<std::pair<int, char>, int> seats{};
public:
// Add a constructor that takes in the `seats` map
Vehicle(std::map<std::pair<int, char>, int> s) : seats(std::move(s)) {}
void displaySeats();
};
and then for each child class:
class MiniVan : public Vehicle {
private:
std::string type = "MiniVan";
public:
// call the parent constructor passing in the seat map
MiniVan() : Vehicle({{1,'A'},0 }, ...}) {}
};
Another approach would be to make a virtual function on the base class like:
class Vehicle {
...
protected:
...
const std::map<std::pair<int, char>, int>& get_seats() const = 0;
};
that the displaySeats function would call instead of directly loading this->seats. Each child class would need to define get_seats(), but that would be pretty easy (pretty much just return seats;). Hopefully that makes sense, let me know if not!

Iterate over a list of objects

In JavaScript I might iterate over a set of objects containing data, like this:
const components = [
{
id: 1,
pin: "A0",
name: "light"
},
{
id: 2,
pin: "A1",
name: "sound"
},
{
id: 1,
pin: "A0",
name: "heat"
},
]
for (const component of components) {
const value = analogRead(component.pin);
console.log(`${component.name}:value`)
}
I often have a need to use code like this on the Arduino, but I'm not sure how I'd go about it.
NOTE: I'm not looking for an exact translation of this into C++; I want to know what the standard pattern is for achieving this is when using Arduino.
You can use C structure. To do so you need to declare a structure first describing your object type.
struct component
{
int id;
char pin[10];
char name[50];
};
component components[] = {
{
1,
"A0",
"light"},
{
2,
"A1",
"sound"},
{
1,
"A0",
"heat"}
};
int main ()
{
int len = sizeof(components)/sizeof(components[0]);
for (int i=0 ; i<len ; i++)
{
printf("{ id: %d , pin: \"%s\" , name: \"%s\" }\n",components[i].id, components[i].pin, components[i].name);
}
return 0;
}
Output:
{ id: 1 , pin: "A0" , name: "light" }
{ id: 2 , pin: "A1" , name: "sound" }
{ id: 1 , pin: "A0" , name: "heat" }
If you're using modern C++ (11 or newer, which I understand arduino support), and your data is stored in an array you can simply do the following:
int values[5] = { 16, 2, 77, 40, 12071 }
for(auto const& value: values) {
// Do stuff
}

d3.js function to count data belonging to a category and bigger than 0

I am trying to create a function that counts the people of each category that have a value bigger than 0. If this is my data...
DATA.CSV
name; category; value
name1; A; 10
name2; A; 0
name3; A; 5
name4; B; 7
name5; B; 3
name6; C; 0
...I should get the following results
count(dataset, "A")=2
count(dataset, "B")=2
count(dataset, "C")=0
EDIT! I am actually loading data from a .json file
[
{
"voce":"amministrazione",
"categoria":"funzioni",
"val2015":404571081
},
{
"voce":"sociale",
"categoria":"funzioni",
"val2015":235251679
},
{
"voce":"territorio e ambiente",
"categoria":"funzioni",
"val2015":286164667
},
{
"voce":"viabilità e trasporti ",
"categoria":"funzioni",
"val2015":144185664
},
{
"voce":"istruzione",
"categoria":"funzioni",
"val2015":168774925
},
{
"voce":"cultura ",
"categoria":"funzioni",
"val2015":55868045
},
{
"voce":"sport",
"categoria":"funzioni",
"val2015":27219432
},
{
"voce":"turismo",
"categoria":"funzioni",
"val2015":9544845
},
{
"voce":"sviluppo economico",
"categoria":"funzioni",
"val2015":14790363
},
{
"voce":"servizi produttivi",
"categoria":"funzioni",
"val2015":4334
},
{
"voce":"polizia locale",
"categoria":"funzioni",
"val2015":99007202
},
{
"voce":"giustizia ",
"categoria":"funzioni",
"val2015":12147068
},
{
"voce":"anticipazioni di cassa",
"categoria":"rimborso prestiti",
"val2015":304323808
},
{
"voce":"finanziamenti a breve termine",
"categoria":"rimborso prestiti",
"val2015":0
},
{
"voce":"prestiti obbligazionari",
"categoria":"rimborso prestiti",
"val2015":38842996
},
{
"voce":"quota capitale di debiti pluriennali",
"categoria":"rimborso prestiti",
"val2015":0
},
{
"voce":"quota capitale di mutui e prestiti",
"categoria":"rimborso prestiti",
"val2015":128508755
},
{
"voce":"spese per conto terzi",
"categoria":"",
"val2015":232661261
},
{
"voce":"disavanzo di amministrazione",
"categoria":"",
"val2015":0
}
]
I tried a for loop with an if statement inside but it is not working.
function count (dataset, chosenCategory) {
var count = 0;
for (d in dataset) {
if (d.categoria==chosenCategory && d.val2015>0) {
count += 1;
} else {
count += 0;
}
}
}
What am I doing wrong?
have you tried changing "d.value" to "+d.value"?
If they're from a csv file, values are generally loaded as strings, so everything you want to treat as a number needs converted to a number, and the '+' does that.
try it in your console
"1">0
false
+"1">0
true
PS. You don't need the else condition

How do I declare a multi-dimensional array in C++?

The following is an example of a multi-dimensional array declaration in C#:
var Number = new double[2, 3, 5]
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82, 1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12, -166.07, 4444.26, 408.62 }
},
};
I would like to do the same in C++, but do not know how and have not read my C++ book.
How can I accomplish this?
Here is a naive way of doing that without explicitly specifying the bounds:
vector<vector<vector<double>>> v =
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82, 1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12, -166.07, 4444.26, 408.62 }
},
};
However, the vector of vectors will allow you to push elements into each dimension freely (they are just independent vectors), so you might end up not having a consistent multi-dimensional vector. In particular, the compiler won't detect any attempt to put more or less elements into one dimension than into another one.
If that is a concern, you might want to check Boost.MultiArray.
You don't need the standard library, or Boost, to define and initialize a fixed size multidimensional array.
double Number[2][3][5] =
{
{
{ 12.44, 525.38, -6.28, 2448.32, 632.04 },
{-378.05, 48.14, 634.18, 762.48, 83.02 },
{ 64.92, -7.44, 86.74, -534.60, 386.73 }
},
{
{ 48.02, 120.44, 38.62, 526.82, 1704.62 },
{ 56.85, 105.48, 363.31, 172.62, 128.48 },
{ 906.68, 47.12, -166.07, 4444.26, 408.62 }
},
};

Problems accessing pre-defined array of floats in C++

I'm trying to make use of precalculated values by outputting them to a header file and then compiling them for use.
The precalculated values are cube co ordinates mapped onto a sphere and the data structure takes the form of:
typedef float heightMapCubeFace[5][5][3];
I am defining each face seperately like so:
heightMapCubeFace face1 = {{{ -2.88675, -2.88675, -2.88675 }, { -3.38502, -3.38502, -1.44338 }, { -3.53553, -3.53553, 0 }, { -3.38502, -3.38502, 1.44338 }, { -2.88675, -2.88675, 2.88675}},
{{ -1.44338, -3.38502, -3.38502 }, { -1.69251, -4.38986, -1.69251 }, { -1.76777, -4.67707, 0 }, { -1.69251, -4.38986, 1.69251 }, { -1.44338, -3.38502, 3.38502}},
{{ 0, -3.53553, -3.53553 }, { 0, -4.67707, -1.76777 }, { 0, -5, 0 }, { 0, -4.67707, 1.76777 }, { 0, -3.53553, 3.53553}},
{{ 1.44338, -3.38502, -3.38502 }, { 1.69251, -4.38986, -1.69251 }, { 1.76777, -4.67707, 0 }, { 1.69251, -4.38986, 1.69251 }, { 1.44338, -3.38502, 3.38502}},
{{ 2.88675, -2.88675, -2.88675 }, { 3.38502, -3.38502, -1.44338 }, { 3.53553, -3.53553, 0 }, { 3.38502, -3.38502, 1.44338 }, { 2.88675, -2.88675, 2.88675}}
};
and finally:
heightMapCubeFace * heightMapSaved[6] = {&face1, &face2, &face3, &face4, &face5, &face6};
Eventually the data structue will be bigger I hav ejust set it to 5x5 to make things easier at first.
The problem I am having is when I want to get the values back, something weird is happening and as a result access violations are occuring.
As shown in the following image
As you can see the assigned value does not match that of the data structure. Instead the value for index [0][0][0][1] is given the value of index [0][0][1][0].
here
I picked up on this because an unhaddled exception is thrown at a later stage (access violation), I think it is because of this index problem but can't be certain.
I don't understand what is going on, am I dereferencing the pointer wrong?
Any help would be much appriciated, thanks.
Here is the code for that section:
for(int i = 0; i < 6; i++)
{
for(int j = 0; j < heightMapRes; j++)
{
for(int k = 0; k < heightMapRes; k++)
{
float xCoord = *(heightMapSaved[i][j][k][0]);
float yCoord = *(heightMapSaved[i][j][k][1]);
float zCoord = *(heightMapSaved[i][j][k][2]);
float newValue = myModule.GetValue( xCoord, yCoord, zCoord);
heightMap.SetValue( j, k, newValue);
}
}
}
layout is (heightMapSaved[6])[5][5][3] not (heightMapSaved[5][5][3][6])