Is it possible to browse a structure? - c++

I need to fill a structure every 10 mS, in this strucure there are 230 variables, only bool and int. My thinking was first to fill and intialize randomly one by one all the variable. But it's very long to write and seems like very ugly code. Also this structure change often.
So my second thinking was to browse the structure ( maybe using a loop ? ) and fill randomly every variable.
After some research, I can't find anything. So, Is there a way to browse my structure and to fill the variable randomly ?
Thank you for your help.
EDIT : Here's what I try to do :
I've got a header file containing the structure :
typedef struct
{
/// Statut Ground-Flight
int _statutGroundFlight;
/// Statut Capteur de presence
bool _statutCapteurPrensence;
/// Statut Bouton OPEN in
bool _statutBoutonOpenIn;
/// Statut Bouton OPEN ext
bool _statutBoutonOpenExt;
/// Statut Bouton CLOSE in
bool _statutBoutonCloseIn;
/// Statut Bouton CLOSE ext
bool _statutBoutonCloseExt;
...
And here's what I want to do every 10 mS:
//Create a structure
struct myStruct;
//Browse the structure
for(int i; myStruct.size(); ++i){
if(myStruct[i] is int){
//Fill it randomly with int
}
if(mystruct[i] is bool){
//Fill it randomly with bool
}
}

I don't think there is a way to browse the structure and fill the variables as you want, but you can avoid writing codes by using macro.
You can write macro and let the pre-processor to generate the code for you ..
for example:
create one struct.def where you can define required fields
#ifndef INTEGER
#error "INTEGER not defined"
#endif
#ifndef BOOL
#error "BOOL not defined"
#endif
#ifndef create_struct
#error "create_struct not defined"
#endif
create_struct(my_struct,
INTEGER(i1)
BOOL(b1,false)
INTEGER(i2)
INTEGER(i3)
BOOL(b2,true)
BOOL(b3,false)
BOOL(b4,false)
INTEGER(i4)
//add or modify fields here
)
#undef INTEGER
#undef BOOL
#undef create_struct
Then write macro in your code by using above file
#include "stdio.h"
#include "string.h"
//create structure
#define INTEGER(var_name) int var_name;
#define BOOL(var_name,data) bool var_name;
#define create_struct(struct_id,data_type)\
typedef struct struct_id##_tag{\
data_type\
}struct_id;
#include "struct.def"
//-------------------------------------------
//function to initialize default value
#define INTEGER(var_name) p->var_name=0;
#define BOOL(var_name,data) p->var_name=data;
#define create_struct(struct_id,data_type)\
void initialize_##struct_id(struct_id* p)\
{\
data_type\
}
#include "struct.def"
//-------------------------------------------------
//function to fill random value to structure
#define INTEGER(var_name) p->var_name=rand();
#define BOOL(var_name,data) p->var_name=rand()%2;
#define create_struct(struct_id,data_type)\
void fill_random_##struct_id(struct_id* p)\
{\
data_type\
}
#include "struct.def"
//-----------------------------------------
Now if you run preprocessor then it will generate the below mentioned code for you....
typedef struct my_struct_tag{
int i1;
bool b1;
int i2;
int i3;
bool b2;
bool b3;
bool b4;
int i4;
}my_struct;
void initialize_my_struct(my_struct* p) {
p->i1=0;
p->b1=false;
p->i2=0;
p->i3=0;
p->b2=true;
p->b3=false;
p->b4=false;
p->i4=0;
}
void fill_random_my_struct(my_struct* p) {
p->i1=rand();
p->b1=rand()%2;
p->i2=rand();
p->i3=rand();
p->b2=rand()%2;
p->b3=rand()%2;
p->b4=rand()%2;
p->i4=rand();
}
Now, if you want to change your structure then you need to change in only one place that is in struct.def file
You can check the link http://rajenpandit.blogspot.in/p/using-macro.html for further details.

I would opt to use std::map to store values of your members.
class MyStructure
{
std::map< unsigned int, int > integerValues;
std::map< unsigned int, bool > booleanValues;
public:
bool & exampleBoolean = booleanValues[ 0 ];
int & exampleInteger = integerValues[ 0 ];
void randomIntegers() {
for( auto & integer : integerValues )
integer.second = randomInteger(); // put your favorite random here
}
};
This way you will change only the place data is actually stored, not the way that you have accessed your structure.
I would recommend making enum with field names to index a map.

An easy approach is to group the same-type fields, then create a union with type-specific arrays.
Example at ideone.com
#include <iostream>
using namespace std;
union X
{
struct
{
int i1, i2, i3;
bool b1, b2, b3;
};
struct
{
int is[3];
bool bs[3];
};
};
std::ostream& operator<<(std::ostream& os, const X& x)
{
os << "{ ";
for (int i = 0; i < 3; ++i)
os << x.is[i] << ' ' << x.bs[i] << ' ';
return os << '}';
}
int main()
{
for (int i = 0; i < 3; ++i)
{
X x;
for (int j = 0; j < 3; ++j)
{
x.is[j] = rand();
x.bs[j] = rand() % 2;
}
std::cout << x << '\n';
}
}
(Of course you should do something better than hard-coding the array dimensions wherever it's indexed, and allow the number of ints and bools to vary independently, but that's all trivial....)
Sample output:
{ 1804289383 0 1681692777 1 1957747793 1 }
{ 719885386 0 596516649 1 1025202362 1 }
{ 783368690 1 2044897763 0 1365180540 0 }

You cannot iterate over fields of a structure like you want.
If this is for a test, then you should not adapt the structure to suit the test. Instead, just do it the "hard" way - filling each field. This is also important because different fields certainly have different ways of being "random". For example _statutGroundFlight probably cannot be ANY integer value; it probably has a set of valid values to test.

Related

Store dynamic amounts of data in a class C++

I have a class that stores data and within the class I have an array called 'position' that stores strings of 2 characters. Unfortunately, the amount of 2 character strings it should hold will vary:
class shipStatus
{
public:
char* name;
int x{};
char position[x][2]; // does not work
void setInfo(char name[], int x);
void displayStatus();
};
The setInfo function assigns a numerical value to x, which varies among objects. I would like the value of x to also dictate the length of the character array 'position'.
For example:
if x = 3 then
char position[3][2]; // the length of the second array is always 2
How can I make my code do this? If I try adding a variable as the parameters my code does not compile.
Here is my setInfo function:
void shipStatus::setInfo(char name[], int x)
{
name = name;
x = x;
}
Since this is C++, you should use the C++ facilities that are available to you. In your case, it would be std::string, std::vector, and std::array.
Below is an example using basically what your original shipStatus structure consisted of, and changing it to using the above mentioned constructs:
#include <string>
#include <array>
#include <vector>
#include <iostream>
class shipStatus
{
std::string name; // <-- Replaced char*
std::vector<std::array<char, 2>> position; // <-- A vector of an array that has a size of 2
public:
void setInfo(std::string n, int x);
void displayStatus();
void setPosition(size_t whichItem, char c1, char c2);
size_t getNumPositions() const;
};
void shipStatus::setInfo(std::string n, int x)
{
name = n;
position.resize(x); // <-- All we need to do is resize() to dynamically resize the vector
}
void shipStatus::displayStatus()
{
for (auto& p : position)
std::cout << p[0] << " " << p[1] << "\n";
}
void shipStatus::setPosition(size_t whichItem, char c1, char c2)
{
position[whichItem] = {c1, c2}; // <-- we set one item in the vector, and in
// that item, we set the [0] and [1] characters
}
size_t shipStatus::getNumPositions() const { return position.size(); }
int main()
{
shipStatus sStatus;
sStatus.setInfo("Ship 1", 3);
sStatus.setPosition(0, '4', '2');
sStatus.setPosition(1, 'a', 'b');
sStatus.setPosition(2, 'y', 'z');
std::cout << "Number of positions: " << sStatus.getNumPositions() << "\n";
sStatus.displayStatus();
}
Output:
Number of positions: 3
4 2
a b
y z
Note that we no longer need x as a member, since a std::vector knows its size already by calling the size() member function.
char **position;
position = (char **)malloc(sizeof(char *)*x);
for (int i=0; i<x; ++i)
{
position[i] = (char *)malloc(sizeof(char)*2);
}
This is a classic "C" way of doing it, will work in C++ too.
For a cleaner approach, we should use vectors/lists for this purpose.

C++ Making a 2D boolean matrix

I am making a program where I have 2 vectors (clientvec and productslist) and I need to create a 2D boolean matrix where the columns is the size of productslist vector and the lines is the size of clientvec vector, but it gives me this error:
"expression must have a constant value"
Here is the code I used:
unsigned int lines = clientvec.size();
unsigned int columns = productslist.size();
bool matrixPublicity[lines][columns] = {false};
Pls help me..
Edit: I am new at c++ so assume I know nothing xD
Edit2: I already know for the answers that I cannot initialize an array with non constant values, now the question is how can I put them after initialize...
The error message is clear: :expression must have a constant value"
It means the array dimension cannot be of variable type. Only enums or pre-processor defined constants are valid.
See for more info:
Why can't I initialize a variable-sized array?
Edit: Since you mentioned you are new to C++, here is a piece of code that might help you:
#include <iostream>
#include <vector>
#include <bitset>
int main()
{
unsigned int lines = 10;
const unsigned int columns = 5;
std::vector<std::bitset<columns>> matrixPublicity;
matrixPublicity.resize(lines);
for(int i=0; i < lines; i++)
{
for(int j=0; j < columns; j++)
std::cout << matrixPublicity[i][j] <<' ';
std::cout<<'\n';
}
}
note that in this case, columns must be constant.
Edit 2: And if the size of lines are not the same, then you must stick to vector types:
typedef std::vector<bool> matrixLine;
std::vector<matrixLine> matrixPublicity;
now you can use resize method for the i-th line of the matrix, e.g.
matrixPublicity[1].resize(number_of_columns_in_line_2);
What you are trying to do would be the same as this:
std::vector<unsigned int> v1 { 1, 2, 3, 4, 5 };
std::vector<unsigned int> v2 { 6, 7, 8, 9 };
bool mat[v1.size()][v2.size()] = false;
This is how the compiler will interpret it without the temporaries and this is invalid. When you declare an array of any type its size has to be known at compile time.
bool mat[2][3] = false; // still invalid
bool mat[2][3] = { false }; // Okay
const int x = 5;
const int y = 7;
bool mat[x][y] = false; // invalid
bool mat[x][y] = { false }; // okay
// Even this is invalid
std::vector<int> v1{ 1, 2, 3 };
std::vector<int> v2{ 4, 5, 6, 7 };
const std::size_t x1 = v1.size();
const std::size_t y1 = v2.size();
bool mat2[x1][y1] = { false }; // Still won't compile.
Value to declare an array must be a constant expression.
Instead of making an array as you have tried to do, you could make a class template that will construct a matrix like object for you. Here is what I have come up with, now the overall design or pattern of this template will fit your condition but the actual implementation to generate the internal matrix will depend on your data and what you intend.
#include <vector>
#include <iostream>
#include <conio.h>
template <class T, class U>
class Matrix {
private:
std::vector<T> m_lines;
std::vector<T> m_cols;
std::vector<U> m_mat;
std::size_t m_size;
std::size_t m_lineCount;
std::size_t m_colsCount;
public:
Matrix() {};
Matrix( const std::vector<T>& lines, const std::vector<T>& cols ) :
m_lines(lines),
m_cols(cols),
m_lineCount( lines.size() ),
m_colsCount( cols.size() )
{
addVectors( lines, cols );
}
void addVectors( const std::vector<T>& v1, const std::vector<T>& v2 ) {
m_lines = v1;
m_cols = v2;
m_lineCount = m_lines.size();
m_colsCount = m_cols.size();
for ( unsigned int i = 0; i < m_lineCount; ++i ) {
for ( unsigned int j = 0; j < m_colsCount); j++ ) {
// This will depend on your implementation and how you
// construct this matrix based off of your existing containers
m_mat.push_back(m_lines[i] & m_cols[j]);
}
}
m_size = m_mat.size();
}
std::size_t size() const { return m_size; }
std::size_t sizeRows() const { return m_lineCount; }
std::size_t sizelColumns() const { return m_colsCount; }
std::vector<U>& getMatrix() const { return m_mat; }
std::vector<T>& getLines() const { return m_lines; }
std::vector<T>& getColumns() const { return m_columns; }
bool operator[]( std::size_t idx ) { return m_mat[idx]; }
const bool& operator[]( std::size_t idx ) const { return m_mat[idx]; }
};
int main() {
std::vector<unsigned> v1{ 1, 0, 1, 1, 0 };
std::vector<unsigned> v2{ 0, 1, 1, 1, 0 };
Matrix<unsigned, bool> mat1( v1, v2 );
int line = 0;
for ( unsigned u = 0; u < mat1.size(); ++u ) {
line++;
std::cout << mat1[u] << " ";
if ( line == mat1.sizeRows() ) {
std::cout << "\n";
line = 0;
}
}
std::cout << "\nPress any key to quit.\n" << std::endl;
_getch();
return 0;
}
Output
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
With this template class you can create a matrix of any type U by passing in two vectors for type T. Now how you construct the matrix will be implementation dependent. But this class is reusable for different types.
You could have two vectors of type doubles, and construct a matrix of unsigned chars, or you could have two vectors of user defined class or struct types and generate a matrix of unsigned values. This may help you out in many situations.
Note: - This does generate a compiler warning, no errors though and it prints and displays properly, but the compiler warning generated by MSVS 2015 is warning C4800: unsigned int: forcing value to bool true or false (performance warning)
This is generated for I am doing a bit wise & operation on to unsigned values; but that is why I set my initial vectors to be passed to this class template's constructor to have all 1s & 0s as this is meant for demonstration only.
EDIT - I made an edit to the class because I noticed I had a default constructor and had no way to add vectors to it, so I added an extra member variable, and an addVectors function, and moved the implementation from the defined constructor to the new function and just ended up calling that function in the defined constructor.
Creating an array isn't that difficult :)
A matrix (2D/3D/...-array) is unfortunately a little bit different if you want to do it your way!
But first of all you should know about the stack and the heap!
Lets have a look at these 2:
Stack:
A stack variable/array/matrix/... is only valid between the nearest 2 -> {} <- which you normally call a "codeblock". The size of it was defined during the "compile time" (the time where the compiler translates your code into the machine language). That means the size of your array needs to be set.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
std::cin >> size;
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' which is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//this is not valid!
int intArray[size()] = {};
return 0;
}
Heap:
A heap variable/array/matrix/... is valid until you delete it. That also means that a heap var is created during the run-time(from starting your program until you close/stop it)! This is allows you to define it's size.
Example:
#include <iostream>
#define MACRO 128
int arraySize(int size){
return size;
}
int main() {
//this is valid
int intArray[128] = {}; //the size(here: 128) needs to be a number like
//or a macro like 'MACRO' whic is
//compile-time-only as well
//this is valid
int intArray2[MACRO] = {};
//creating an array with a non-static size
//works like this:
//int can also be a 'bool'
int* intArray = new int[arraySize()];
// ^ the star means you are pointing to
//an adress inside of your memory which has
//the size of an int (per element)
//That's why they are called "pointers"!
//Right now it points to the beginning of the
//array.
// ^ the keyword "new" says that
//you are allocating memory on the heap.
// ^
//then you have to say which kind of array
//it is which is the same you gave the pointer
// ^
//now you give it the size of that array
//this time it can be return value or the size
//of a variable
//as I mentioned...you have to delete this array on your own
//if you dont do that your program will crash
//maybe not after starting but it will!
//SO NEVER NEVER NEVER... forget about it
delete intArray[];
//^ write delete
// ^
//then the name of your array
// ^
//at the end of it write these 2 brackets
//thex say you wanna remove the whole array!
//why? because you can also create/delete
//heap variables not only arrays.
return 0;
}
Creating a matrix on the heap is unfortunately not that easy.
But it is essential to know how a 1D-array works before going to further dimensions! That's why I did this tutorial!
Klick here to see how to create a matrix on the heap
Klick here to learn more about the heap
Klick here to choose the best result of this theme
I hope I could help you :)!

de-serialize ASCII to struct

I have come up with the following structure to declare various formats if messages that are to be received from the network:
#include <stdint.h>
#include <iostream>
#include <string.h>
template<int T>
struct uint
{
static uint<T> create(uint64_t value)
{
uint<T> r = {value};
return r;
}
uint(uint64_t value)
{
v = value;
}
uint()
{}
uint<T>& operator =(uint64_t value)
{
v = value;
return *this;
}
operator uint64_t() const
{
return (uint64_t)v;
}
unsigned long long v:T;
}__attribute__((packed));
example:
typedef uint<5> second_t;
suppose one of the message formats (which are auto-generated via some process) is like this:
struct seconds
{
char _type;
second_t _second;
} __attribute__((packed));
Now suppose I would like to populate an instance of the above messahe using a string:
int main()
{
seconds ii;
const char *i = "123456";
// memset, memcpy,sprintf... ??? what to use here?
std::cout << ii._type << " " << ii._second << std::endl;
}
Given a stream 123456, I expect the instance of the seconds (ii) structure to have char ii._type = '1' and integer ii._second = 23456. But I dont know how to do that. Do you have a clue how i can do that? and do you have any suggestion how to improve the basic structure?
thanks
You have a number of easier and more reliable options available that require almost no work.
check out google protocol buffers (platform independent message serialisation and deserialisation): https://developers.google.com/protocol-buffers/
or boost::serialization - (probably faster, but not platform-independant) http://www.boost.org/doc/libs/1_58_0/libs/serialization/doc/index.html

Same variable for different datatypes?

I have to call one simple functions with different datatypes in c++. eg,
void Test(enum value)
{
int x;
float y; // etc
if(value == INT)
{
// do some operation on x
}
else if(value == float)
{
// do SAME operation on y
}
else if(value == short)
{
// AGAIN SAME operation on short variable
}
.
.
.
}
Thus I want to eliminate the repetitive code for different datatypes ...
So , I tried to use macro ,depending on values of enum, to define same variable for different datatypes .. but then not able to differentiate between the MACROS
e.g.
void Test(enum value)
{
#if INT
typedef int datatype;
#elif FLOAT
typedef float datatype;
.
.
.
#endif
datatype x;
// Do operation on same variable
}
But now every time the first condition #if INT is getting true.
I tried to set different values of macro to differentiate but not working :(
Can anyone help me achieve the above thing.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
//type generic method definition using templates
template <typename T>
void display(T arr[], int size) {
cout << "inside display " << endl;
for (int i= 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int a[10];
string s[10];
double d[10];
for (int i = 0; i < 10; i++) {
a[i] = i;
d[i] = i + 0.1;
stringstream std;
std << "string - "<< i;
s[i] = std.str();
}
display(a, 10); //calling for integer array
display(s, 10); // calling for string array
display(d, 10); // calling for double array
return 0;
}
If you really want your function to be generic, template is the way to go. Above is the way to do and call the method from main method. This might be of some help for you to reuse a function for different types. Pick up any tutorial or C++ books for complete understanding on templates and get a grip of the full concepts. Cheers.
You can use templates to achieve you purpose.
Simply write a template function which take the value in the function argument which is of generic type and put the operational logic inside it. Now call the function with different data types.
I advice you to use function overloading:
void foo(int arg) { /* ... */ }
void foo(long arg) { /* ... */ }
void foo(float arg) { /* ... */ }
Supposing you want do the same operation with integer and long types you can eliminate the code repetition in this way:
void foo(long arg) { /* ... */ }
void foo(int arg) { foo((long) arg); }

array of 2s power using template in c++

Can we create the following array or something similar using template in c++ at compile time.
int powerOf2[] = {1,2,4,8,16,32,64,128,256}
This is the closest I got.
template <int Y> struct PowerArray{enum { value=2* PowerArray<Y-1>::value };};
but then to use I need something like PowerArray <i> which compiler gives error as i is dynamic variable.
You can use BOOST_PP_ENUM for this:
#include <iostream>
#include <cmath>
#include <boost/preprocessor/repetition/enum.hpp>
#define ORDER(z, n, text) std::pow(z,n)
int main() {
int const a[] = { BOOST_PP_ENUM(10, ORDER, ~) };
std::size_t const n = sizeof(a)/sizeof(int);
for(std::size_t i = 0 ; i != n ; ++i )
std::cout << a[i] << "\n";
return 0;
}
Output ideone:
1
2
4
8
16
32
64
128
256
512
This example is a modified version (to suit your need) of this:
Trick : filling array values using macros (code generation)
Nothing against using BOOST_PP_ENUM but I think your going for more of the kind of code I will show you.
What I would do, is I would make a constructor of your type class which just sets the array to the stuff you need. That way it does it as soon as the program builds and it stays nice and neat. AKA the proper way.
class Power
{
public:
Power();
void Output();
// Insert other functions here
private:
int powArray[10];
};
Then the implementation would be with a basic "for loop" to load them into the array you just created.
Power::Power()
{
for(int i=0;i<10;i++){
powArray[i] = pow(2,i);
}
}
void Power::Output()
{
for(int i=0;i<10;i++){
cout<<powArray[i]<<endl;
}
}
Hopes this helps...