Copy values to and from a member of a structure in C++ - c++

I have a structure as shown below, which I use for the purpose of sorting a vector while keeping track of the indices.
struct val_order{
int order;
double value;
};
(1). Currently what I do is use a loop to copy values as shown below. So my first question is if there is a faster way to copy values to a member of a structure (not copying an entire structure to another structure)
int n=x.size();
std::vector<val_order> index(n);
for(int i=0;i<x.size();i++){ //<------So using a loop to copy values.
index[i].value=x[i];
index[i].order=i;
}
(2). My second question has to do with copying one member of a structure to an array. I found a post here that discusses using memcpy to accomplish that. But I was unable to make it work (code below). The error message I got was class std::vector<val_order, std::allocator<val_order> > has no member named ‘order’. But I was able to access the values in index.order by iterating over it. So I wonder what is wrong with my code.
int *buf=malloc(sizeof(index[0].order)*n);
int *output=buf;
memcpy(output, index.order, sizeof(index.order));

Question 1
Since you are initializing your n vectors from two different sources (array x and variable i), it would be difficult to avoid a loop. (you could initialize the vectors from index.assign if you had an array of val_order already filled with values, see this link)
Question 2
You want to copy all n order values into a int array, and memcpy seems convenient for that. Unfortunately,
each element of a vector is a val_order structure, so even though you could copy via memcpy that would not only copy the int *order* value but also the double *value* value
furthermore, you are dealing with vector, which internal structure is not a simple array (vector allows operations that are not possible with a regular array) and thus you cannot copy a bunch of vector to a int array by simply giving the address of, say, the first vector element to memcpy.
also, memcpy wouldn't work like you want anyway, but it expects an address - thus you would have to give, e.g., &index[0] ... but again, this is not what you want given the points above
So you would have to make another loop instead, like
int *buf = (int *)malloc(sizeof(int)*n);
int *output = buf;
for (int i=0 ; i<n ; i++) {
output[i] = index[i].order;
}

Related

C++ vector of custom template class and unclean (?) allocation

I have a quite complex Problem and couldn't find out, where the Problem is. Part of the Problem might be, that i didn't fully understand the data structures. I have the following custom template class, with this member variables:
template <class T>
class Matrix
{
private:
T * *M; /* array of row pointers */
size_t n_rows, /* number of rows */
n_cols; /* number of columns */
size_t row_start, /* first row of submatrix */
col_start, /* first column of submatrix */
origcols; /* refers to original matrix */
bool hasownvalues, /* has matrix own value? */
initialized; /* are matrix values initialed? */
I also made a custom constructor, which makes a 2D array out of a file with tab-separated data:
Matrix(const std::string &filename)
{ do.stuff }
I'm not sure, if it is really important how this exactly works, it quite a bunch of code. if so, i could edit it later, but the constructor works well as long as i declare a single variable for such an object.
My problem occurs when i try to make a bunch of the objects and try to wrap them up in a vector. Lets say i have x different files, each containing data for a matrix. I also have a vector in which the filenames are stored:
std::vector<std::string> filenames{};
for (int idx = 3; idx < argc; idx++)
{
filenames.push_back(argv[idx]);
}
So far this code works and it is mandatory that i keep it unchanged to keep the rest of the program working.
The following is flexible and thats where i have problem:
std::vector<Matrix<T>> coredata; /* initialize the vector for the wrap */
...
for (auto& it : filenames)
{
Matrix<T> M(it); /* call the special constructor*/
coredata.push_back(M); /* add new object to the vector */
}
The first assignment works well, but from the second on it seems that it appends the new Matrix, but also overwrites the old one or at least a part of it. And in the third one i get a segmentation fault when running the program.
Some information of the program around:
the constructor works with space allocated by the "new" command, maybe that could be part of the problem.
the real size of the Matrix object isn't known before run time. (the arrays can be of different size), but i could arrange, that the read data in fact always is of the same size
T is constant within the vector. it can't happen, that M is sometimes Matrix int and sometimes Matrix float
the vector would be embedded in another superclass and the snippet above is part of a constructor of this class, coredata is a member variable.
I'm quite puzzled what the problem exactly is. Maybe some variables don't live long enough. I also thought of assigning just a reference to the address in the vector, but as far as i understand, a vector already stores just a reference, so it seems not that plausible.
I also thought of initializing the vector with a bunch of "0"-matrices and then overwrite them with the constructed objects. But i don't know how to do that and on top of that,
i don't know at compile time how many rows and columns the read Matrices will have.
Maybe a vector isn't a useful solution at all, i also thought of making a plain C-array.
But there i have the problem again, that i have to initialize this array first and can't just append another Matrix-Object to it.

Find End of Array Declared as Struct Type C++

I was recently learning to use struct datatype in c++. I know how the basics of struct datatype work and how to manipulate its variables. But I was wondering how would I determine the end of struct datatype array. For example consider the code below:
struct PersonDetails
{
string name, address;
int age, number;
}
Now in c++ program I create an array of struct type as follows:
PersonDetails Data[500];
Now consider that I have 30 records in data array and I have to display these records by looping through data array's index. So how would I determine that I have to loop through only first 30 indexes as the data is only stored in these indexes. As in char array we compare all indexes with '\0' to determine the end of array. Then what method will we use for Data[] array?
An edit that I have no idea about Vectors and the project i am working on requires me to use basics of c++(functions, control structures, loops, etc.).
It's not feasible.
For char[], back in times of C standardization, developers agreed to use \0 (integer value 0) as a special character marking end-of-string. Everything works as long as everyone is following this convention (i.e. both standard library functions and developers using those functions).
If you wanted to have such a convention for your type, you could just write down "Data object with both strings empty and both ints equal to 0 is array terminator", but you would have to follow this convention. You'd have to write functions that would stop processing array upon finding such an object. You'd have to make sure that in every array there is at least one such object.
Instead
You should use std::vector<Data> which can automatically accomodate for any number of Data objects and will now precisely how many of them are currently stored (using size() method)
or
use std::array<Data, 30>, which can store exactly 30 objects and you can assume all of them are valid objects.
IMHO the correct way to solve this is to not use a C-style array, but instead use a std::array or std::vector that knows it's .size().
Iterating a std::vector or std::array is trivial:
for (const auto& element : Data_array) {
// Do something with the array element
}
See also:
https://en.cppreference.com/w/cpp/container/array
https://en.cppreference.com/w/cpp/container/vector
https://en.cppreference.com/w/cpp/language/for
https://en.cppreference.com/w/cpp/language/range-for
The simplest solution is to just have a separate variable specifying how many array elements are filled in.
PersonDetails Data[500];
int numPersons = 0;
Data[0].name = ... ;
Data[0].address = ...;
Data[0].age = ...;
Data[0].number = ...;
numPersons = 1;
Data[1].name = ... ;
Data[1].address = ...;
Data[1].age = ...;
Data[1].number = ...;
numPersons = 2;
...
Then you use that variable when looping through the array.
for (int i = 0; i < numPersons; ++i)
{
// use Data[i] as needed...
}
I don't really agree using std::array makes any difference.
The problem you currently have doesn't occur in whether we have such an element in the container, but whether the element we are inspecting useful.
Consider the example you gave, for an array of chars, we simply check whether one of the elements is \0 to decide whether or not we should halt the iteration.
How does that work? The ramaining elements, of course, default initialized to be \0, they exist, but of no use.
Similarly, you can check, in this example, whether
name.empty()
Or, in order to avoid any possible exception, as mentioned in the comment section, do this:
add user-defined constructor to the class ( or struct, they are same actually.) which initialize age to -1 and then check if age == -1.
because it's impossible for a people not having any name, that means, you have not assign to any of the remaining elements. Thus, stop iteration.
As a supplement, using std::vector makes sense, but if that isn't a option for you for the time being, you don't need to consider it.

C++ Class Variables: Initialization vs. Assignment and Initialization of vectors

I am working on a C++ program that has a series of class variables that contain vectors on some or all of the member variables. My question is three-fold:
Is it straight-forward to use constructors to initialize vector variables that are part of a class (see sample class definition below)? Could someone post an example constructor for the class below (or for at least the single and two-dimension vector variables)?
Is there a problem with simply initializing the variables myself in my code (i.e., iterating through each element of the vectors using loops to assign an initial value)?
Along the same lines, if the variables need to be initialized to different values in different contexts (e.g., zero in one instance, some number in another instance), is there a way to handle that through constructors?
Sample class definition:
class CreditBasedPoolLevel {
public:
int NumofLoans;
int NumofPaths;
int NumofPeriods;
double TotalPoolBal;
vector<int> NumofModeled;
vector<double> ForbearanceAmt;
vector<double> TotalAmtModeled;
vector<vector<int>> DefCountPoolVector;
vector<vector<double>> TermDefBalPoolVector;
vector<vector<double>> BalloonDefBalPoolVector;
vector<vector<double>> TermDefBalPoolVectorCum;
vector<vector<double>> TermSeverityAmt;
vector<vector<double>> TermELAmtPoolVector;
vector<vector<double>> BalloonELAmtPoolVector;
vector<vector<double>> TermELAmtPoolVectorCum;
};
In C++, initializing a variable calls its constructor. In a vector's case, this means it creates an instance of a vector with whatever the initial capacity is (10 I believe), with no values. At this point, you need to use push_back in order to fill the vector - even though it has a capacity, it will cause undefined behavior if you try to access unfilled areas directly (such as with NumofModeled[0]). You can also initialize it with some amount of space by using vector NumofModeled(x) (x being the number of spaces), but generally because vectors have dynamic size, it's easier to use push_back unless there is some reason you need to enter your data out of order.
Relates to the capacity part of one, if you try to access unfilled space in a vector you will get undefined behavior. It's pretty standard practice to fill a vector with a loop though, such as:
vector<int> v;
int in = 0;
while (cin)
{
cin >> in;
v.push_back(in);
}
Yes, but remember that like functions, constructors only differentiate by the type of input parameters. So, for example, you could have CreditBasedPoolLevel(int level) and CreditBasedPoolLevel(vector<int> levels), but not another with the definition CreditBasedPoolLevel(int otherint), because it would conflict with the first. If you want to be able to take different contextual input of the same type, you can use another variable to define the constructor type, such as CreditBasedPoolLevel(int input, string type) and use a switch block to define the initialization logic based on the type.
As for question number three, simply add a constructor with an argument that is the value you want to initialize the vectors with.
And if you just want the vectors to be default constructed, then there's nothing that needs to be done.
Constructor may look something like this:
CreditBasedPoolLevel::CreditBasedPoolLevel()
{
const int numDefCountPools = 13;
const int numDefCountPoolEntries = 25;
for(int i = 0; i < numDefCountPools; i++)
{
vector<int> v;
for(int j = 0; j < numDefCountPoolEntries; j++)
{
v.push_back(j + i * 5); // Don't know what value you ACTUALLY want to fill here
}
DefCountPoolVector.push_back(v);
}
}
Note that this is ONE solution, it really depends on what values you want, how you went them organized, etc, what is the "right" solution for your case.

C++ assign array of ints to an empty array of ints same size

I am very familiar with Java and this is allowed there. However it looks like it's not with C++. I'm getting an "invalid array assignment" when trying to assign valuesToGrab = updatingValues;.
//these are class attributes
int updatingValues[361] = {0};
int valuesToGrab[361] = {0};
//this is part of a function that is causing an error.
for (unsigned int i=0; i < 10; i++) {
//this fills values with 361 ints, and num_values gets set to 361.
sick_lms.GetSickScan(values,num_values);
//values has 361 ints, but a size of 2882, so I copy all the ints to an array
//of size 361 to "trim" the array.
for(int z = 0; z < num_values; z++){
updatingValues[z] = values[z];
}
//now I want to assign it to valuesToGrab (another program will be
//constantly grabbing this array, and it can't grab it while it's being
//populated above or there will be issues
valuesToGrab = updatingValues; // THROWING ERROR
}
I don't want to have to iterate through updatingValues and add it to valuesToGrab one by one, but if I have to I will. Is there a way I can assign it in one function with C++?
Thanks,
The standard idiom for copying in C++ is
#include <algorithm>
...
std::copy(values, values+num_values, updatingValues);
make sure updatingValues is large enough or you will get overruns and bad things will happen.
That said in C++ we generally use a std::vector for this sort of task.
#include <vector>
...
std::vector<int> updatingValues=values; //calls vectors copy constructor
I vector does everything an array does (including static initalization in C++11), but has a well define interface. with iterators, size, empty, resize, push_back and more.
http://en.cppreference.com/w/cpp/algorithm/copy
http://en.cppreference.com/w/cpp/container/vector
EDIT
It is also worth noting that you can combine vector and arrays.
std::vector<int> vect(my_array, my_array+10);
//or
std::vector<int> another_vector;
...
another_vector.assign(my_array, my_array+10);//delayed population
and visa-versa
std::copy(vect.begin(), vect.end(), my_array); //copy vector into array.
First of all, I don't think this will do what you're looking for because valuesToGrab = updatingValues; will overwrite your valuesToGrab every cycle of the outer loop.
Assuming you did want to do this though, and you didn't want to change to a vector:
std::copy(updatingValues, updatingValues+361, valuesToGrab);
will do it. You can treat a normal array just like a std:: container in any std::algorithm, the pointers count as random access iterators.
Rethink your design though, you shouldn't need to "trim" and you probably don't need to copy.
In C++, the idiomatic container to use in place of arrays is std::vector. With vector or with arrays, you can use the std::copy() function from the <algorithm> header, which is the preferred way of copying containers of any sort in C++. With vector:
std::vector<int> updatingValues, valuesToGrab;
// Ensure the vector has sufficient capacity to accept values.
updatingValues.resize(361);
// Copy values from the array into the vector.
std::copy(values, values + 361, updatingValues.begin());
// Source begin & end; Destination begin.
// Copy one vector to another.
valuesToGrab = updatingValues;
With arrays:
std::copy(valuesToGrab, valuesToGrab + 361, updatingValues);
Again with just arrays, if you are going for more of a C style, you can use the C standard library function memcpy(), from <cstdlib>:
memcpy(valuesToGrab, updatingValues, 361 * sizeof(int));
// Destination; Source; Number of bytes.
With memcpy() (and its cousin, memmove()), you must be careful about the size of the elements you’re copying; if you say 361 instead of 361 * sizeof(int), you’ll copy 361 bytes, not 361 ints’ worth of bytes—a big difference.
Keep in mind that arrays are implemented as pointers in C and C++.
In particular an array on the stack can be visualized as a pointer to a constant location in memory that has the capacity that you requested for the array. This memory is on the stack. When you try valuesToGrab = updatingValues, you could think of this as trying to copy the address of updatingValues to the variable valuesToGrab. This is NOT attempting a deep copy, which you seem to be attempting. However, valuesToGrab points to a constant location in memory and cannot be updated. The standard is a little more specific on this and explicitly forbids the assignment of arrays, which is why you're getting the specific error that you're seeing.
You will need to use a loop or something like std::copy or C's memcpy to copy the values from one array to the other.

C++ Array of Objects

I have an array in a class that should hold some instances of other objects. The header file looks like this:
class Document {
private:
long arraysize;
long count;
Row* rows;
public:
Document();
~Document();
}
Then in the constructor I initialize the array like this:
this->rows = new Row[arraysize];
But for some reason this just sets rows to an instance of Row rather than an array of rows. How would I initialize an array of Row objects?
Both SharpTooth and Wok's answers are correct.
I would add that if you are already struggling at this level you may be better off using a std::vector instead of a built-in array in this case. The vector will handle growing and shrinking transparently.
This should work. One possible "error" would be an incorrect value for arraySize.
However you should better use a std::vector from the standard library for that purpose.
#include <vector>
class Document {
// ...
std::vector<Row> rows;
// ...
};
and in your constructor:
Document::Document() : rows(arraySize) { // ... }
or
Document::Document() { rows.assign(arraySize, Row()); }
If arraySize contains a reasonable value at that point you actually get an array. I guess you trust your debugger and the debugger only shows the 0th element (that's how debuggers treat pointers), so you think there's only one object behind that pointer.
For i in [0;arraysize[, *(this->rows+i) should be an instance of row.
What precisely makes you think that rows is only one element? Make certain that you arraysize isn't 1. If it is, you'll get an array of 1 element. Mind you, you must still call delete [] with an array of size 1.
Also, why is arraysize different than count? Using that terminology, you should be making an array of count elements and arraysize should be equal to sizeof(Row) * count.
Also, you specifically ask "How would I initialize an array of Row objects?". Do you mean allocate? If so, that's how you would do so. If you mean initialize, the default constructor of Row will be called on each element of the array when the array is allocated.