undefined length array in class constructor - c++

I've been trying to use arrays in a class constructor. Here is my code:
struct Motor_Group{
int Motors[3];
int Encoder;
};
int main()
{
Motor_Group Left_Drive {{2,3},3};
Motor_Group Right_Drive {{2,3},3};
cout<< sizeof(Left_Drive.Motors)/sizeof(int);
return 0;
}
But, the problem is that i want to make the length of the array motors to be undefined untill its contents is declared. How can i do that?
Thanks for your kind help!

If you do not need MotorGroups to be of the same type,
then you could template the array size.
Using std::array
#include <array>
#include <iostream>
template<size_t motor_count>
struct Motor_Group{
std::array<int,motor_count> Motors;
int Encoder;
};
int main()
{
Motor_Group<2> Left_Drive {{2,3},3};
Motor_Group<3> Right_Drive {{2,3,4},3};
std::cout<< Left_Drive.size();
// Left_Drive = Right_Drive; // Error at compile time, since Motor_Group<2> != Motor_Group<3>
return 0;
}

Related

How do I pass a function with an argument of a structure passed by reference?

I was working on my program and noticed that it doesn't compile. I was wondering why I can't pass my structure array as an array of references. My code is down below
#include <iostream>
#include <cstring>
using namespace std;
struct a{
int name;
};
void input(a & array1[10]){
for(int i=0;i<10;i++){
array1[i].name=i+1;
}
}
void print(a & array1[10]){
for(int i=0;i<10;i++){
cout<<array1[i].name<<endl;
}
}
int main(){
a array1[10];
input(array1[10]);
print(array1[10]);
}
When you pass an array into a function:
<opinion> The array degrades to a pointer. So you might as well have the
function declare the parameter as a pointer, "a*", instead of as an
array, a[].
The function has no idea how many items are in the array parameter. You should get in the habit of passing "size" as a parameter to a function when you pass the array.
On the flip side, arrays passed as pointers are inherently a reference parameter not a value (copy of) parameter. So you are implicitly meeting your goal of passing your array and all the items in the array by reference.
This is probably what you want.
#include <iostream>
#include <cstring>
using namespace std;
struct a {
int name;
};
void input(a* array, size_t count){
for(int i=0; i<count; i++) {
array[i].name = i + 1;
}
}
void print(a* array, size_t count) {
for(int i=0; i<count; i++) {
cout<<array[i].name<<endl;
}
}
int main() {
a array1[10] = {}; // zero-init the array of a's
input(array1, 10);
print(array1, 10);
}
Your syntax to pass the array by reference is wrong.
Please see the working code below.
#include <iostream>
#include <cstring>
using namespace std;
struct a{
int name;
};
void input(a (&array1)[10]){
for(int i=0;i<10;i++){
array1[i].name=i+1;
}
}
void print(a (&array1)[10]){
for(int i=0;i<10;i++){
cout<<array1[i].name<<endl;
}
}
int main(){
a array1[10];
input(array1); // make sure you simply pass the array name
print(array1);
}
Try it out yourself
As enforced by the syntax of the language parenthesis that enclose array1 as in (&array1) are necessary. If you don't use them you're simply passing an array of reference not a referene to an array.
array1[10] is the 10th element of the array(which actually in your case doesn't exists, it's simply out-of-array-bound access), instead you need to pass the address of the first element of the array which is the same as array name i.e. the array name decays to a pointer.

How to copy elements from std::list to an array of struct?

I need to copy the contents of a std::list into an array, wherein the array is struct of array. Below is the code implementation of it.
#include <iostream>
#include <string>
using namespace std;
typedef struct
{
int height;
int width;
int length;
}dimensions;
GetDimensions(list<std::string>, *int); // Function that copies the content of list to array passed as second parameter
int main()
{
dimensions cuboid[10];
int plane[10];
list<std::string> planeList = GetList();//Function that returns list of elements
list<std::string> dimensionList = GetList();
GetDimensions(planeList,&plane);//This is fine, as it is a simple array
GetDimensions(dimensionList,&cuboid.height);//Trouble in implementation of this usecase, for cuboid.height, cuboid.width and cuboid.height.
return 0;
}
GetDimensions(list<std::string>dimensionList, int* dimensionParams)
{
int i=0;
for(list<std::string>::iterator it = dimensionList.begin(); it != dimensionList.end(); ++it)
{
dimensionParams[i] = stoi(*it);
i++;
}
}
Here, I need GetDimensions() function to copy the list (passed as first parameter) to array (second parameter). The implemented function works well for simple array plane. But how to pass the array of struct as parameter to the function ?
I will be getting the std::list as cuboid.height, cuboid.width and cuboid.length. So the function has to copy the contents of list from cuboid[0].height to cuboid[i].height respectively. Is there any specific function to copy the content directly?
Use std::array 's instead. Then your problem can be reduced to passing two different types of arrays to a single function.
This can be solved
either by good old function overloads
or in c++17 function template with
if-constexpr.
Following is an example code with templated function with if-constexpr (See live online)
#include <iostream>
#include <string>
#include <list>
#include <array>
#include <type_traits> // std::is_same_v
struct dimensions // no need to typedef here
{
int height;
int width;
int length;
};
template<typename T>
void GetDimensions(const list<std::string>& dimensionList, T& dimensionParams)
^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //---> pass list by const-ref as the values are non-modifying
{
int i{0};
if constexpr (std::is_same_v<std::array<int, 10>, T>)
{
for(const std::string& str: dimensionList) dimensionParams[i++] = std::stoi(str);
}
else
{
for(const std::string& str: dimensionList) dimensionParams[i++].height = std::stoi(str);
}
}
int main()
{
std::array<dimensions, 10> cuboid; // use std::array instead of VLA
std::array<int, 10> plane;
std::list<std::string> planeList{"1", "2"}; // some list
std::list<std::string> dimensionList{"1", "2"};
GetDimensions(planeList, plane);
GetDimensions(dimensionList, cuboid);
return 0;
}
Also note that:
You have not specified the return type of GetDimensions function.
You probably want to return void there.
in C++ you do not need to use typedef alias for struct { ... }.
last but not least, do not practice with using namespace std;
You can do this with boost::transform_iterator.
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <boost/iterator/transform_iterator.hpp>
struct dimensions {
int height;
int width;
int length;
};
template <typename OutputIt>
void GetDimensions(std::list<std::string> dimensionList, OutputIt dimensionParams)
{
// N.b. taking the address of a standard library function is undefined, so wrap in a lambda
auto stoi = [](std::string s){ return std::stoi(s); };
std::copy(boost::make_transform_iterator(dimensionList.begin(), stoi),
boost::make_transform_iterator(dimensionList.end(), stoi),
dimensionParams);
}
int main() {
dimensions cuboid[10];
int plane[10];
std::list<std::string> planeList = GetList();
std::list<std::string> heightList = GetList();
std::list<std::string> widthList = GetList();
std::list<std::string> lengthList = GetList();
GetDimensions(planeList, plane);
GetDimensions(heightList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::height)));
GetDimensions(widthList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::width)));
GetDimensions(lengthList,
boost::make_transform_iterator(cuboid, std::mem_fn(&dimensions::length)));
return 0;
}

c++ struct with bool array member. How use in main code

struct thread_data
{
int seq, packetNum;
bool ackTally[4];
};
main:
bool boolArray[4];
data[j].packetNum = 3;
data[j].seq = 1;
data[j].ackTally = boolArray;
Running this code gives me this error
error: incompatible types in assignment of bool [1] to bool [0]
data[j].ackTally = boolArray;
How do I resolve this in code? (It may not be relevant by I'll probably want to change some of these values later within the main code)
C-style arrays cannot be assigned. There are two simple ways around this:
First, use std::copy instead of assignment:
#include <algorithm>
#include <iterator>
struct thread_data
{
int seq, packetNum;
bool ackTally[4];
};
int main() {
thread_data data;
bool boolArray[4];
// Initialize boolArray.
std::copy( std::begin(boolArray), std::end(boolArray),
std::begin(data.ackTally) );
}
Or second, replace your C-style arrays with std::array. One of several benefits of std::array is that it can be assigned:
#include <array>
struct thread_data
{
int seq, packetNum;
std::array<bool, 4> ackTally;
};
int main() {
thread_data data;
std::array<bool, 4> boolArray;
// Initialize boolArray.
thread_data.ackTally = boolArray;
}
Arrays can not be assigned. Each element must be copied in a loop. You don't have to write that loop yourself though, since there is an algorithm for that in the standard library: std::copy.
P.S. Copying from boolArray will have undefined behaviour because its values are indeterminate.

Structure Arrays & Pointers

I have to use a struct array called Robot_parts[] for each part_rect struct (part_num, part_name, part_quantity, part_cost)
And through the void display function, I have to display Robot_parts[] array entirely through pointer but I don't know how, and I don't know where to declare Robot_parts[] and whether i have to put any number value inside the brackets.
So far I have:
#include <iostream>
#include <string>
using namespace std;
void display();
struct part_rec
{
int part_num;
string part_name;
int part_quantity;
double part_cost;
};
int main()
{
part_rec Robot_parts[ ] = {
{7789, "QTI", 4, 12.95},
{1654, "bolt", 4, 0.34},
{6931, "nut", 4, 0.25}
};
return 0;
}
void display()
{
cout<<Robot_parts[]<<endl<<endl;
}
If I also made a few other errors, please let me know. Thanks!
As stated in a comment it would be much better to use a c++ container like a std::vector or std::array.
But since your professor requires an old-style array, you could try like the code below - see the comments for explanation:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct part_rec
{
int part_num;
string part_name;
int part_quantity;
double part_cost;
};
// You have to pass a pointer (to the array) and the size of the array
// to the display function
void display(part_rec* Robot_parts, int n);
// Make a function so that you can "cout" your class directly using <<
// Note: Thanks to #BaumMitAugen who provided this comment and link:
// It makes use of the so called Operator Overloading - see:
// https://stackoverflow.com/questions/4421706/operator-overloading
// The link is also below the code section
std::ostream &operator<<(std::ostream &os, part_rec const &m)
{
// Note - Only two members printed here - just add the rest your self
return os << m.part_num << " " << m.part_name;
}
int main()
{
part_rec Robot_parts[] {
{7789, "QTI", 4, 12.95},
{1654, "bolt", 4, 0.34},
{6931, "nut", 4, 0.25}
};
display(Robot_parts, 3);
return 0;
}
void display(part_rec* Robot_parts, int n)
{
// Loop over all instances of your class in the array
for (int i = 0; i < n; ++i)
{
// Print your class
cout << Robot_parts[i] << endl;
}
}
The link recommended by #BaumMitAugen:
Operator overloading

Declare in .h and initialize in .cpp

I want to declare a pointer in my .h and initialize it in .cpp. For example an int pointer:
My .h class file:
#pragma once
#include <iostream>
#include <stdio.h>
#include <stdint.h>
using namespace std;
class Calc_ToF_low
{
private:
int telo[3];
public:
Calc_ToF_low(void);
~Calc_ToF_low(void);
double * CalcToF(int16_t * señal, int fs);
long double * filter(long double *ganancias, long double *coeficientes, double *señal,int lensignal, int L, int control);
void signal_p1_lowf(void);
void avg_p1_lowf(void);
void time_est();
};
My .cpp class file:
#include "Calc_ToF_low.h"
Calc_ToF_low::Calc_ToF_low(void)
{
telo[3]={0,1,2};
}
How can I do this?
Like this:
Calc_ToF_low::Calc_ToF_low() // note no need to say void in C++
{
telo[0]=0;
telo[1]=1;
telo[2]=2;
}
Or if you can use C++11, something like this might work:
Calc_ToF_low::Calc_ToF_low()
: telo{{0,1,2}} // initializer list, will not work in "old" C++98
{}
You could just assign values to it by typing:
telo[0] = 0;
telo[1] = 1;
telo[2] = 2;
in your .cpp.
It may not be perfect for huge arrays but then you probably should assign the values from a file instead.
If you're initializing large arrays with a constant value for all item, you can use this approach:
Calc_ToF_low::Calc_ToF_low(){
memset(telo, 0, sizeof(telo)); //0 is the constant value
}
If you want to initialize your large array to some set of values that has no patterns:
int defaultTeloData[TELO_NUMITEM] = {2,4,1,5,6,1,7,82,41,6,134,88,1};
Calc_ToF_low::Calc_ToF_low(){
memcpy(telo, defaultTeloData, sizeof(telo));
}
If your array values has pattern, use a loop and some formulas or constructors.
Calc_ToF_low::Calc_ToF_low(){
for(int a = 0; a sizeof(telo)/sizeof(telo[0]); a++){
telo[a] = dataFormulaForTelo(a);
}
}
This is one way you could do it:
#include <array>
class Calc_ToF_low
{
private:
std::array<int, 3> telo;
public:
Calc_ToF_low();
};
Calc_ToF_low::Calc_ToF_low()
: telo()
{
for(unsigned i = 0; i<telo.size(); ++i)
telo[i] = i;
}