Vector of structs which contains another vector - c++

I need to have dynamically allocated space of structs and those structs have to contain another dynamically allocated. If I do it by manual allocation, that would laborious.
So I want to do it through vectors:
using namespace std;
struct lol{
int value;
vector<int> vekt;
};
vector<lol> vektt;
It is logically, that I am going to do it like the code above but I dont know how to do 2 things that I am going to need for my program:
1.iterate through both of them to get values
2.push something into vekt( the vector of struct );
I tried something like this for pushing but doesnt work:
vektt[0] . vekt . push_back( 2 );
So I need to know how to iterate through both of these vectors and how to access members and methods of the vector vect.

// Iterating
for (auto &i: vektt) // or const auto &i according to requirements
{
cout << i.value << ", ";
for (auto j: i.vekt) cout << j << ' ';
cout << '\n';
}
// Inserting int to vekt of i-th element of vektt
int a;
vektt[i].vekt.push_back(a);

Related

C++ Creating Dynamic 2D Array With One Statement but Without auto

I've seen that a dynamic 2D array in C++ can be created as follows:
auto arr{ new int[nRows][nCols] };
nRows and nCols are compile-time known and the size of the array will not change during runtime.
I've tested what is the type of arr is PAx_i (where x is nCols). But I cannot figure out what to put instead of auto (if I don't want to use it) to create a dynamic 2D array with a single statement.
So, the question: Is it possible in C++ to specify the type of a dynamic 2D array directly (C-style like)? If yes, how?
C++ does not support dynamically-sized raw arrays (aka Variable Length Arrays, or VLAs). Whenever you come across the need for such a dynamic array (how ever many dimensions it may have), you should be immediately thinking of using the std::vector container.
Once properly created, you can use the [] operator (concatenated, for 2-D vectors) in much the same way as you would with raw arrays.
Here's a short code demo that creates a dynamic, 2-dimensional 'array' of integers, using the std::vector class, and initializes all elements with an especially significant, non-zero value:
#include <iostream>
#include <vector>
int main()
{
size_t nCols, nRows;
std::cout << "Enter nRows and nCols: ";
std::cin >> nRows >> nCols;
if (nCols < 2 || nRows < 2) {
std::cout << "Matrix is too small!\n";
return 1;
}
// The following SINGLE LINE declares and initializes the matrix...
std::vector<std::vector<int>> arr(nRows, std::vector<int>(nCols, 42));
std::cout << "nRows = " << arr.size() << "\n";
std::cout << "nCols = " << arr[0].size() << "\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
// Demo for how to use the "[][]" operator ...
arr[0][0] = arr[nRows - 1][nCols - 1] = 33; // Change 1st and last
std::cout << "------------\n";
for (auto& row : arr) {
for (auto i : row) {
std::cout << i << " ";
}
std::cout << std::endl;
}
return 0;
}
One of the great benefits of using std::vector over new[] is that you don't have to worry about subsequently calling delete[] – the container class takes care of all memory allocation and deallocation internally.
In C++ try to avoid new/delete unless you have no other choice.
Next up is std::make_unique (or std::make_shared).
For dynamic arrays C++ has 'std::vector'
Like this :
#include <vector>
#include <iostream>
int main()
{
// 2x2 vector
std::vector<std::vector<int>> values{ {0,1},{2,3},{4,5} };
std::cout << values[1][1];
return 0;
}
Thusly, vector of vector, in this case the values are uninitialized.
std::vector<std::vector<int>> arr(nRows,std::vector<int>(nCols));
You can also do this with gcc compiler, but its not per standard, and won't work if nRows or nCols is variable in Visual Studio:
int arr[nRows][nCols];
It's better for you to get comfortable with C++ standard library, as it will open up new worlds for you.
Another way:
int *arr = new int[nRow*nCol];
You can then index into the flat buffer like:
arr[0][1]

What is the proper way to create a dynamic array of unique_ptr's in c++11?

I would like to identify a canonical approach to allocating the equivalent of an array of pointers to pointers to int (like: int ** int_array), but using unique_ptr.
I would like a C++11 solution that is extensible to an array of pointers to pointers to an instance of a class, if possible (I've used ints here to simplify, and I realize there may be other issues when using class instances).
I understand how to create a fixed-size array of unique_ptr where the size is known in advance. The goal is to do the same where the array size is not known.
I have looked at a number of related solutions including the one below, but they seem to deal only with fixed allocation of unique_ptr arrays (that is, the size of the array of unique_ptr is already known in advance):
Proper way to create unique_ptr that holds an allocated array
I've implemented a simple program that attempts to demonstrate and compare 3 approaches: traditional dynamic creations of pointers, a fixed array of unique_ptr, and the goal: a dynamic array of unique_ptr.
#include <iostream> // include iostream
#include <memory> // include memory
using namespace std;
int main() {
cout << "Testing dynamic arrays of pointers\n";
int **num_array; // typical dynamic array of pointers to int
int count; // count of ints the user wants to generate
unique_ptr<int[]> f_num_array(new int[200]());
// above: fixed array of unique pointers to int - not what I want
unique_ptr<int[]> u_num_array;
// above: GOAL: dynamic array of unique pointers to int
int sum, u_sum, f_sum;
// above: test sum of each type of array (should match user count)
cout << "How many pointers would you like? ";
cin >> count; // get user input
num_array = new int*[count]; // allocate array of pointers on heap
//u_num_array = new int[count](); // GOAL - would like to do this
// above: ERROR: no overload for =; cannot allocate this way
for(int i=0; i<count; i++) { // allocate ints and store pointer
num_array[i] = new int(1); // pointer to an int on the heap
f_num_array[i] = 1; // assign 1 to the pre-allocated unique pointer array
unique_ptr<int> u_tmp(new int(1)); // temporary unique_ptr to int
// u_num_array[i] = u_tmp; // GOAL - would like to do this...
// ERROR: cannot assign unique_ptr this way
}
sum = 0; f_sum = 0; u_sum = 0; // init our sums to verify
for(int i=0; i<count; i++){
sum += *(num_array[i]); // summing our traditional array of pointers
f_sum += f_num_array[i]; // summing our fixed unique array of pointers
}
cout << "Sum = " << sum << "\n";
cout << "Sum (fixed unique_ptr array) = " << f_sum << "\n";
cout << "Sum (dynamic unique_ptr array) = " << u_sum << "\n";
delete[] num_array; // delete the dynamic array
f_num_array.release(); // delete the dynamic array
cout << "\nDone!\n";
}
#include <iostream>
#include <memory>
#include <vector>
int main() {
std::cout << "Testing dynamic arrays of pointers\n";
//int **num_array; - Never use except you are forced by some external interface.
int count = 0; // Always initialize variables
std::vector<std::unique_ptr<int>> num_array;
std::cout << "How many pointers would you like? ";
std::cin >> count; // get user input
num_array.resize(count);
for (auto& p : num_array) // You can do it with some algorithm, but I prefer this way
p = std::make_unique<int>(1);
int sum = 0; // Don't declare variables before you use them.
for (auto& p : num_array)
sum += *p;
std::cout << "Sum = " << sum << "\n";
num_array.clear();
std::cout << "\nDone!\n";
}

Array like data structure with negetive index in C++

I need a structure to keep track of presence of some items. I just wanted to take an array a0....aN and mark the elements as a[0]=0,a[1]=0,a[2]=1........(a[i]=1 if the element is present,a[i]=0 if element is not present).
But the items range from -1000 to +1000. It can be done by putting the negative range from 1001 to 2000. I needed to know if there is any other data structure in c++ that can work like array and with negative indexes. Thank you for your time.
map is used for this only, to have key/index of any basic/user-defined data type. See - http://www.cplusplus.com/reference/map/map/
Example for your case:
#include <iostream>
#include <map>
#include <string>
int main ()
{
std::map<int, int> mymap;
mymap[-1]=1;
mymap[-2]=0;
mymap[-3]=1;
std::cout << mymap[-1] << '\n';
std::cout << mymap[-2] << '\n';
std::cout << mymap[-3] << '\n';
return 0;
}
Example for char:
#include <iostream>
#include <map>
#include <string>
int main ()
{
std::map<char,std::string> mymap;
mymap['a']="an element";
mymap['b']="another element";
mymap['c']=mymap['b'];
std::cout << "mymap['a'] is " << mymap['a'] << '\n';
std::cout << "mymap['b'] is " << mymap['b'] << '\n';
std::cout << "mymap['c'] is " << mymap['c'] << '\n';
std::cout << "mymap['d'] is " << mymap['d'] << '\n';
std::cout << "mymap now contains " << mymap.size() << " elements.\n";
return 0;
}
You an create your own data structure which supports -ve indexes. Just add an offset to the indexs while storing them in an array.
class MyArray {
int *arr;
public:
MyArray(int offset) {
arr = new int[2*offset]; // size must to double the offset
}
~MyArray(){
delete arr;
}
void add(int index, int val) {
arr[index + offset] = val;
}
void get(int index) {
return arr[index + offset];
}
}
Then you can just use your class to add and get elements with any index.
MyArray arr = MyArray(1000); // pass max -ve index as offset
arr.add(10, -150);
cout << arr.get(100);
I need a structure to keep track of presence of some items.
If what you want is set semantics, use a set data structure.
No need to implement a custom array wrapper.
You can use a std::set (or std::unordered_set) for that. Remember that "premature optimization is the root of all evil".
Insert the values that are there, leave out the values that are missing. No need to worry about negative indices.
You can use the methods std::set::find() or std::set::count() to check the presence of an item. Have a look at the documentation to find some example code.
If you later find it's a performance critical optimization, you can replace a std::set<int> with a data structure that you wrote yourself on the basis of an array of bits anytime. If it's not, doing so prematurely might turn out to be an unnecessary source of unexpected errors and a waste of time.
For reference:
http://en.cppreference.com/w/cpp/container/set
http://en.cppreference.com/w/cpp/container/unordered_set
http://en.cppreference.com/w/cpp/container/set/find
http://en.cppreference.com/w/cpp/container/set/count
How to check that an element is in a std::set?
Most efficient approach will be just shifting your array indexes so all of them are non-negative. In your case just use a[i+1000] and it will be sufficient.
If you really need to use negative indexes it is also possible.
C / C++ calculates memory address of array element using address of table and then adding index value to it. Using negative numbers just points to memory area placed before your table (which is not you normally want).
int a[2001];
int *b = &a[1000];
int x = b[-1000]; // This points to 1000 places before b which translates to a[0] (valid place)
Another approach will be using containers. Then any number can be translated to string and stored in proper container.
I think that the answer of #Rajev is almost fine. I have just replaced a plain array with a std::vector. Thus, the memory management is secure and copying and moving is easy.
template <typname T>
class MyArray {
private:
std::vector<T> arr;
public:
MyArray(int offset) {
arr.resize(2*offset); // size must to double the offset
}
void set(int index, int val) {
arr[index + offset] = val;
}
void get(int index) {
return arr[index + offset];
}
}
You can expand this further by overloading the operator [] of MyArray.

Using an array in a for loop - C++

I want to set a test condition to determine the size of an array, and then move through each value of the array in a for loop.
Take this array for example
std::string expenses[] = {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
The brackets are empty, and there are 10 elements in there. How would you create a for loop for this without creating a separate variable that holds an int of 10?
Use the countof macro, declared like this:
#define countof(a) (sizeof(a)/sizeof((a)[0]))
so you can say:
for (i = 0; i < countof(expenses); i++) ...
As everybody's pointing out, you gotta be a good enough hot-shot to know the difference between an array and a pointer.
If you pass a pointer to expenses, of course, countof will be bogus.
My immediate inclination would be to tell you to use a vector instead of an array. With a vector, you can get the size quite easily, and (better still) avoid getting the size by using a range-based for loop:
std::vector<std::string> expenses {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
// print out the strings, one per line:
for (auto const &s : expenses)
std::cout << s << "\n";
If you really have to use an array instead of a vector, you can use a function template to compute the size:
template <class T, size_t N>
size_t size(T (&array)[N]) {
return N;
}
for (int i=0; i<size(expenses); i++)
std::cout << expenses[i] << '\n';
The primary advantage of this template function over the usual macro ((sizeof(x)/sizeof(x[0]))) is that it's strongly typed--any attempt at passing a pointer instead of an array simply won't compile (and given how easy it is for an array's name to decay to a pointer, that's significant).
If you have C++11 available, you can use the std::begin and std::end from the standard library to accomplish (roughly) the same:
for (auto s = std::begin(expenses); s != std::end(expenses); ++s)
std::cout << *s;
Note that although std::begin and std::end were added in C++11, you can use code similar to the size template above to create similar templates for a C++98/03 compiler.
template <class T, size_t N>
T *begin(T (&array)[N]) {
return array;
}
template <class T, size_t N>
T *end(T (&array)[N]) {
return array + N;
}
These can also be used with standard algorithms, so you could do something like this:
std::copy(begin(expenses), end(expenses),
std::ostream_iterator<std::string>(std::cout, "\n"));
Again, note that we've avoided dealing directly with the count or creating subscripts into the array, and just deal with iterators into the array, and the items to which those iterators refer.
If you mean to run through each element (within the same scope), then 'The Dark' is correct:
#include <string>
#include <iostream>
int main()
{
std::string expenses[] = {"housing", "utilities", "household expenses", "transportation", "food", "medical", "insurance", "entertainment", "clothing", "misc"};
std::cout<< "NumEls = " << sizeof(expenses) / sizeof(expenses[0]) << std::endl;
}
produces an output of 10, and replacing the cout with a for loop would allow testing of the strings, for example
for (int i=0; i< (sizeof(expenses)/sizeof(expenses[0])); i++)
{
std::cout<< "The " << i << "th string is : " << expenses[i] << std::endl;
}
Note this will produce "0th", "1th", etc...
* Caveat *
Reflecting the comments given in the question, our answers seem incomplete without mention of the fact that the sizeof(POINTER) won't give you useful information - or at least, not useful for this. As such, if you want instead to use:
myFunction (std::string someArray[])
{
for( all the strings in someArray )
{
std::cout << someArray[i];
}
}
then you'll find yourself unable to do so.
Instead, you could use:
myFunction (std::string someArray[], int sizeOfArray)
{
for(int i=0; i<sizeOfArray; i++)
{
std::cout<< someArray[i];
}
}
but this goes exactly against your question (not storing a separate int)
* Enter std::vector *
A simpler solution is to use a std::vector
The use of a vector allows function calls such as myVector.size() and also loops based automatically on the size of the vector, in the case of more recent (C++11) compilers/compiler options.
Vectors can be happily passed into and out of functions, and if you want to change them, references to vectors are also a simple way to do so - referring to your answer:
inputFunction (std::vector<string> &expenses, budget &info)
{
for (int i=0; i< expenses.size(); i++)
{
std::cout<< "Enter your expense for " << expenses[i] << ": ";
// Operation to store input as needed
}
}
On a side note, it seems like you want to link the string for the name of the expense to the value of the expense? If so, consider perhaps using a map. In this case, you'd probably want to consider std::map<std::string, float>.
* Using a std::map *
In using a map, you'll probably want an iterator. An example might be like:
void input(const std::vector<std::string> &exp, std::map<std::string, float> &map)
{
for (int i=0; i<exp.size(); i++)
{
float tempFloat;
std::cout<< "Please enter the amount for " << exp[i] << ": ";
std::cin >> tempFloat;
map.emplace(exp[i], tempFloat);
}
};
and in main(),
std::map<std::string, float> myMap;
input(myVec, myMap);
for (std::map<std::string, float>::iterator it=myMap.begin(); it!=myMap.end(); it++)
{
std::cout << "myMap values -> " << it->first << " = " << it->second << std::endl;
}
This will output each pair you have, using an iterator starting at myMap.begin() and ending at the last entry to your map.
emplace(...) constructs a pair, and then adds it to the map. You should take care not to use insert, which requires a different set of parameters, and is not likely to be what you want here.
The outputs are referenced by iterator->first and iterator->second, the first and second values of each map pair. In this case, those are the string and float that are stored in the map.
You can use sizeof(expenses) / sizeof (expenses[0]). Note that you don't need the brackets, but I prefer it.
A number of people have mentioned the (sizeof(expenses)/sizeof(expenses[0])) trick, but if you're going to go that route, in C++ there is a slightly better way to do it using a templated function:
/* returns # of items in array, or will error out at compile time if you try to pass it a pointer instead of an array */
template<typename T, int size> unsigned int array_size(T(&)[size]) {return size;}
This is safer, since it will give you a compile-time error if you accidentally pass in a pointer rather than an array. (The sizeof() version would compile and then do something unexpected at runtime, which is undesirable)
Two possibilities. If you want to iterate over it in the same scope that you define it, you can simply use a ranged based for loop:
for(auto& expense : expenses)
{
std::cout << expense << std::endl;
}
If you want to be able to pass it to a function, you'd have to to some ugly stuff to fit it into a std::array, then you can use the above range loop on it anywhere.

C++: Why is my vector of structs acting as one struct?

I'm working my way through Accelerated C++ and have decided to mess around with the one of structs that were defined in there. While doing so, I've come across a problem: creating a vector of these structs and modifying the elements in each one seems to modify the elements in all of them.
I realize that this probably means I've initialized all the structs in the vector to a struct at a single memory address, but I used the .push_back() method to insert "dummy" structs in to the vector. I was under the impression that .push_back() pushes a copy of its argument, effectively creating a new struct.
Here is the header for the struct:
#ifndef _STUDENT_INFO__CHAPTER_9_H
#define _STUDENT_INFO__CHAPTER_9_H
#include <string>
#include <iostream>
#include <vector>
class Student_info9{
public:
Student_info9(){homework = new std::vector<double>;};
Student_info9(std::istream& is);
std::string getName() const {return name;};
double getMidterm() const {return midterm;};
double getFinal() const {return final;};
char getPassFail() const {return passFail;};
std::vector<double> *getHw(){return homework;};
void setName(std::string n) {name = n;};
void setMidterm(double m) {midterm = m;};
void setFinal(double f) {final = f;};
private:
std::string name;
double midterm;
double final;
char passFail;
std::vector<double> *homework;
};
#endif /* _STUDENT_INFO__CHAPTER_9_H */
And here is the code that i'm fooling around with (excuse the excessive print statements... the result of some time trying to debug :) ):
vector<Student_info9> did9, didnt9;
bool did_all_hw9(Student_info9& s)
{
vector<double>::const_iterator beginCpy = s.getHw()->begin();
vector<double>::const_iterator endCpy = s.getHw()->end();
return(find(beginCpy, endCpy, 0) == s.getHw()->end());
}
void fill_did_and_didnt9(vector<Student_info9> allRecords)
{
vector<Student_info9>::iterator firstDidnt = partition(allRecords.begin(), allRecords.end(), did_all_hw9);
vector<Student_info9> didcpy(allRecords.begin(), firstDidnt);
did9 = didcpy;
vector<Student_info9> didntcpy(firstDidnt, allRecords.end());
didnt9 = didntcpy;
}
int main(int argc, char** argv) {
vector<Student_info9> students;
Student_info9 record;
for(int i = 0; i < 5; i++)
{
students.push_back(record);
}
for(int i = 0; i < students.size(); i++)
{
students[i].setMidterm(85);
students[i].setFinal(90);
students[i].getHw()->push_back(90);
std::cout << "student[" << i << "]'s homework vector size is " << students[i].getHw()->size() << std::endl;
students[i].getHw()->push_back(80);
std::cout << "student[" << i << "]'s homework vector size is " << students[i].getHw()->size() << std::endl;
students[i].getHw()->push_back(70);
std::cout << "student[" << i << "]'s homework vector size is " << students[i].getHw()->size() << std::endl;
std::cout << "Just pushed back students[" << i << "]'s homework grades" << std::endl;
if(i == 3)
students[i].getHw()->push_back(0);
}
std::cout << "student[3]'s homework vector size is " << students[3].getHw()->size() << std::endl;
for(vector<double>::const_iterator it = students[3].getHw()->begin(); it != students[3].getHw()->end(); it++)
std::cout << *it << " ";
std::cout << std::endl;
std::cout << "students[3] has " << ( ( find(students[3].getHw()->begin(),students[3].getHw()->end(), 0) != students[3].getHw()->end()) ? "atleast one " : "no " )
<< "homework with a grade of 0" << std::endl;
fill_did_and_didnt9(students);
std::cout << "did9's size is: " << did9.size() << std::endl;
std::cout << "didnt9's size is: " << didnt9.size() << std::endl;
}
As you can see by the print statements, it seems that the homework grades are being added only to one Student_info9 object, copies of which seem to be populating the entire vector. I was under the impression that if you were to use consecutive copies of .push_back() on a single object, it would create copies of that object, each with different memory addresses.
I'm not sure if that's the source of the problem, but hopefully someone could point me in the right direction.
Thanks.
When you push a StudentInfo onto the vector, it is indeed copied, so that's not the problem. The problem is the vector containing the homework grades. Since you only store a pointer to that vector in StudentInfo, only the pointer, not the vector, is copied when you copy a StudentInfo. In other words you have many different StudentInfos that all have a pointer to the same homework vector.
To fix this you should define a copy constructor which takes care of copying the homework vector.
Have you learned about the copy constructor yet? If so, think about what is happening with vector<Student_info9> students on push_back().
Specifically, what happens with this pointer.
std::vector<double> *homework;
The line Student_info9 record; constructs a Student_info9 using the first constructor. This first constructor creates a vector and stores a pointer to it as a member variable. You then proceed to add a copy of this Student_info9 to a vector 5 times. Each copy has a pointer to the same vector.
Your StudentInfo9 class contanis a pointer to a std::vector<double>, which means in the default copy constructor (which will be called when you add a StudentInfo9 object to your vector), the pointer itself is copied. That means all of your StudentInfo9 objects have the same homework vector.
Does that make sense? Please refer to http://pages.cs.wisc.edu/~hasti/cs368/CppTutorial/NOTES/CLASSES-PTRS.html for a more in depth look at pointers and copy constructors.