How do I use C++ vectors with a user defined structure? - c++

I am trying to manage an array of structures using vectors but keep getting an error msg.
The vector is declared in the header file as:
vector< TLE_Values, allocator<TLE_Values> > SavedSatellites;
which VS2013 is quite happy with.
The structure is defined as:
struct TLE_Values
{
string CatalogNum;
string SatelliteName;
string DateStr;
string TimeStr;
string Classification;
double DecayValue;
int ElsetNum;
double InclinationValue;
double RaanValue;
double EccentricityValue;
double ArgPerigeeValue;
double PerigeeAngle;
double AvgSpeed;
double Period;
int OrbitNum;
};
and initialised with default values by a constructor.
In the main program code, having determined the number of elements I will require ( CountItemsInFile() ), I try to expand the vector list using:
SavedSatellites.push_back(CountItemsInFile());
This however returns the following compiler error message:
error C2664:
'void std::vector<TLE_Values,std::allocator<TLE_Values>>::push_back(const TLE_Values &)' : cannot convert argument 1 from 'int' to 'TLE_Values &&'
1> Reason: cannot convert from 'int' to 'TLE_Values'
1> No constructor could take the source type, or constructor overload resolution was ambiguous.
Another thread suggested that a vector needed to be initialised with 0, which won't happen with a user defined type like this.
What am I missing? where have I gone wrong? How do I create the initial vector with my structure?
There's lots of documentation for using vectors of type (int) but not much if you're not using integers.

To expand a vector use
SavedSatellites.resize(CountItemsInFile());
If you just want reserve memory for it but keep the size of the vector untouched and ready for subsequent push_back without memory reallocation:
SavedSatellites.reserve(CountItemsInFile());

The docs are key here:
void push_back (const value_type& val);
push_back doesn't take an int, it takes a parameter of the same type your vector holds. You need to give it a TLE_Values object.
You also don't need to preemptively size the vector; you can just keep calling push_back until you're done.

Related

Cannot initialize a variable of type 'double (*)[x]' with an rvalue of type 'double (*)[z]

I have a vector of doubles that I am passing to a lib https://github.com/llohse/libnpy in order to read a numpy file:
std::vector<unsigned long> shape {};
bool fortran_order;
std::vector<double> dataNpy;
const std::string path {"/home/ubuntu/template.npy"};
npy::LoadArrayFromNumpy(path, shape, fortran_order, dataNpy);
I will need to further process this data and have been instructed to use arrays since vector copy is not optimal.
So this data should be a matrix but the lib reads it as linear.
That is why I want to create a pointer to a 2D table with a given size for rows and columns like this with the data from the vector
double (*template_data)[12] = (double (*)[12]) dataNpy.data();
When I do it by explicitly putting the size, like above the compiler is ok with it, however, when I do it like the code below i get an error:
int sizeRows = 12, sizeColumns=12;
double (*template_data)[sizeRows] = (double (*)[sizeColumns]) dataNpy.data();
Cannot initialize a variable of type 'double ( * )[sizeRows]' with an rvalue of type 'double ( * )[sizeColumns]'
Could you explain to me why that is?

Printing a 2D int vector from an object

So I'm pretty sure it's having issues because it's trying to print the pointer instead of the value, but I don't know how to fix it.
class cName {
private:
std::vector< std::vector<int>> *vect2d;
public:
// initializes vector that contains x number of vectors
// that each contain y number of ints
cName(int x,int y);
void printVector(int);
}
void cName::printVector(int x) {
for(int i=0; i<x; i++) {
//have to get size because
// the number of ints in the vector will change
for(int j=0; j< this->vect2d[i].size(); j++)
std::cout << this->vect2d[i][j]<<" ";
std::cout<<"\n";
}
}
I'm having issues printing a 2d vector I use in a class I'm making. I get an error that says:
cannot bind 'std::ostream {aka std::basic_ostream<char>'
lvalue to 'std::basic_ostream<char>&&'
Question:
Could someone explain me why is throwing me that error and help me fix it?
The vect2d member is a pointer to a vector of vectors of ints. You don't really need a pointer here, just use a vector of vectors of ints.
Your usage of this pointer does not produce any immediate errors because the subscript operator array[index] can be used on pointers. If you are not sure that your code is correct, prefer to use the range-checked .at(index) method for std::vector instances. Using an explicit method would have pointed you to your error, since there is no .at(index) method for pointers.
What the compiler currently sees when you call this->vect2d[i].size() is:
this->vect2d of type vector<vector<int>>*, a complicated way of spelling vect2d. Note that this is a pointer type.
this->vect2d[i] of type vector<vector<int>>, which is equivalent to *(vect2d + i), but not to (*vect2d)[i] or vect2d->at(i)! Note that this is not a pointer type, but still two nested vectors.
Therefore, the .size() is called on the vector that is i vector sizes away from your outer *vect2d container. Quite likely, this is invalid memory and could segfault.
When you later do vect2d[i][j], that is actually equivalent to *(vect2d + i)[j] which should behave the same as (vect2d + i)->at(j). But it is not vect2d->at(i).at(j)! Notably, it is of type vector<int> rather than int. That is the cause of your error message: there's no available operator<< to print vectors, so the compiler produces that quite incomprehensible error.

error : no match for 'operator[]'

I am solving a problem in which I m trying to pass address a 2-D array of a structure and trying to manipulate it but, whenever I use [] operator to access the array elements , I get a compile time error:
no match for 'operator[]'
in my codeblocks IDE.
#include <iostream>
using namespace std;
typedef struct mat
{
int data;
int flag;
} cell;
int mat(cell *);
int main()
{
int m,n;
cin>>m>>n;
cell game[n][m];
cout<<"The length of matrix is "<<mat(&game[0][0]);
}
int mat(cell *arr)
{
return (sizeof(arr[0])/sizeof(arr[0][0]));
}
cell game[n][m];
This is not legal C++. You are using a compiler-specific extension. At this point I advise you against using any compiler-specific extensions. Use standard C++ only. In standard C++ there are no Variable Length Arrays. Don't use arrays in your C++ programs. To get proper variable length array functionality. You should use std::vector instead, like this:
std::vector<std::vector<cell>> game;
Further,
&game[0][0]
is not an address of a 2D array. This is an address of the first element in the array. It contains no information about the number of elements. It is lost forever. You cannot pass it to some function and expect the size of the array to be recovered. To get proper array functionality with a built-in size function, use std::vector.
Last but not least,
(sizeof(arr[0])/sizeof(arr[0][0]));
arr is a cell*. arr[0] is a cell. arr[0][0] is invalid because a cell is neither an array not a pointer, nor it has a custom [] operator defined. In any case you cannot use sizeof to recover the number of elements in the array from a pointer to its first element. To get proper array functionality with a built-in size function, use std::vector.
Two things:
Your function takes a pointer to cell but since you're treating it like a 2D array, you should probably change your signature to either accept a cell ** arr or a cell arr[m][] where m is the (fixed) size of the array and must be specified. Note that these data structures have fundamentally different representations in memory - they just have the same [][] syntax for accessing elements.
You can't use the sizeof function to determine the length of an array if you pass it as a pointer to an elem. You will need to pass the dimensions along with your array, like this:
int mat(cell **arr, int m, int n);
The definition being given basically says that your class doesn't define the operator [], meaning you can't use the syntax you are trying to use.

C++ how to convert vector to an array?

Can someone be able to tell me how to convert vector to an array?
I have a function that returns a vector of double type with typical like this
std::vector<double> x_vec = LinspaceArray_DK2(0, 5.0, 0.01);
std::vector<double> y_vec = Calculate_y_vec(x_vec);
However, following GSL (GNU scientific lib) function is expecting an array as an input
gsl_spline_init (spline, x_array, y_array, x_vec.length);
Here, x_array, y_array are arrays corresponding to vectors x_vec and y_vec.
I tried following solution here (How to convert vector to array in C++) which suggest conversion like this:
std::vector<double> v;
double* a = &v[0];
But, this type of conversion did not help with gsl_spline_init which expected arrays as inputs.
Updated:
I tried to call like this:
// Convert all vector to an array
double* x_input_Array = &x_input[0];
double* y_input_Array = &y_input[0];
and then call:
gsl_spline_init (spline, *x_input_Array, *y_input_Array, iNoOfPtsIni);
I am getting this error:
error C2664: 'gsl_spline_init' : cannot convert parameter 2 from 'double' to 'const double []'
Thanks,
DK
You do not need (and should not) dereference - the function you call expects arrays, and you pass their first elements. Use
gsl_spline_init (spline, x_input_Array, y_input_Array, iNoOfPtsIni);

How to copy the contents of std::vector to c-style static array,safely?

I need to manipulate data in fixed array involving mid insertion.
Rather than using memcpy,etc. I want to use vector. I have problem when I want
to copy the vector elements back to the c-style array.
Here's the code:
void tryvector()
{
using namespace std;
const int MAX_SIZE=16;
BYTE myarr[MAX_SIZE]={0xb0,0x45,0x47,0xba,0x11,0x12, 0x4e};
vector<BYTE> myvec (myarr, myarr+MAX_SIZE);
vector<BYTE>::iterator it;
printf("myarr pre :");
for(int i=0;i<MAX_SIZE;++i){
printf("%02x ", myarr[i]) ;
}
printf("\nmyvec pre :")
for(it=myvec.begin(); it<myvec.end();++it){
cout<<hex<<static_cast<int>(*it)<<" ";
}
it = myvec.begin()+ 3;
myvec.insert(it,0x5f);
printf("\nmyvec post:");
for(it=myvec.begin(); it<myvec.end();++it){
cout<<hex<<static_cast<int>(*it)<<" ";
}
copy(myvec.begin(), myvec.end(), myarr); //???
printf("\nmyarr post:");
for(int i=0;i<MAX_SIZE;++i){
printf("%02x ", myarr[i]) ;
}
}
I'm using vs 2005.
Here's the warning:
warning C4996: 'std::_Copy_opt' was declared deprecated
1> c:\program files\microsoft visual studio 8\vc\include\xutility(2270) : see declaration of 'std::_Copy_opt'
1> Message: 'You have used a std:: construct that is not safe. See documentation on how to use the Safe Standard C++ Library'
1> c:\documents and settings\mhd\my documents\tesvector.cpp(50) : see reference to function template instantiation '_OutIt std::copy<std::_Vector_iterator<_Ty,_Alloc>,BYTE*>(_InIt,_InIt,_OutIt)' being compiled
1> with
1> [
1> _OutIt=BYTE *,
1> _Ty=BYTE,
1> _Alloc=std::allocator<BYTE>,
1> _InIt=std::_Vector_iterator<BYTE,std::allocator<BYTE>>
1> ]
When I run it , I got the following run-time error:
Run-Time Check Failure #2 - Stack around the variable 'myarr' was corrupted.
Please note that I use vector instead list or deque because
the 'middle insertion' like the code above is juat a particular problem.
It will happen less than 'inserting at the end' and
'random access of element'.
Any solution ?
Any answer that resembles:"You use c++, drop the c style array implementation.
Use only vector for all array implementation" is not really helpful.
Thanks.
The problem is that you're adding things to the vector so it ends up with more elements than were in the myarr array that you initialized it with.
If you want to copy the vector back into the array, you'll need to size it down:
myvec.resize( MAX_SIZE);
Or you could limit the number of elements you copy back:
copy( myvec.begin(), myvec.begin()+MAX_SIZE, myarr);
If you want the myarr array to contain all the elements, then it needs to be larger than MAX_SIZE, and you've found out why people suggest to use vector rather than raw arrays (vectors know how to grow, arrays do not).
Note that while you don't want 'Any answer that resembles:"You use c++, drop the c style array implementation. Use only vector for all array implementation"', you can often get away with using a vector and passing &myvec[0] to routines that expect a raw array. vector is required to store its elements contiguously just like a raw array for just this reason.
Since you're getting the 'unsafe operation' warning, you're using Microsoft's compiler. To fix the problem safely, you're supposed to use the checked_copy algorithm instead of copy. As Evgeny Lazin indicates, you can create a checked iterator for your array to pass to the checked_copy algorithm.
Other options to make the copy safe that do not require Microsoft extensions would be to wrap the array in a class (possibly templated) that keeps track of the array size and provides methods to copy data into the array in a safe manner. Something like STLSoft's array_proxy template or Boost's boost::array might help.
In general, I guess you could do something like this:
void *myarr;
if((myarr = malloc(myvec.size() * sizeof myvec[0])) != NULL)
{
memcpy(myarr, &myvec[0], myvec.size() * sizeof myvec[0]);
/* Do stuff with the C-style array for a while
.
.
.
*/
free(myarr); /* Don't forget handing back the memory when done. */
}
This allocates a new C-style array to hold the vector's elements, and copies the data in place. This way the there is no need to match the sizes statically.
Of course, this is general so it just gives you a void * to access your C array with, so you need to either cast or just change the type to the actual type (BYTE in this case).
You can use template argument deduction to find the array bound:
template<typename T, size_t N>
size_t copy(std::vector<T> const& src, T[N] dest) {
size_t count = std::min(N, src.size());
std::copy(src.begin(), src.begin()+count, dest);
return count;
}
Turn off the Microsoft warnings about unchecked stuff. They're aimed at luring you into writing unportable code.
You can do:
memcpy(myarr, &(myvec)[0], myvec.size())
Edit: As far as safety goes, according to this, vectors store data in contiguous segments of memory, so you can access them "not only using iterators but also using offsets on regular pointers to elements."