dynamically changing name of an array in c++ - c++

Hi I have a problem where at compile time, I don't know how many vectors in my program are needed. The number required depends on a data set given at run-time, which will results in the range of vectors needed to be from 1 to N.
So if the data set requires ten vectors, it will create vec1,vec2,......vecN
How can i dynamically create the vectors so that they all have a different name?
I would then need to call each array separately. Presumably
I could just use strings and a few loops for this.

You can't do that directly. However, you could use a map to store a vector name, and the vector itself:
map<string, vector<int> > myMap;
You can add elements simply like this (if the element with such key doesn't exist yet):
vector<int> vec;
myMap["vec"] = vec;
If you'll do it with a key that already exists, the value will be replaced. For example:
vector<int> vec;
vector<int> vec1;
myMap["vec"] = vec;
myMap["vec"] = vec1;//now myMap["vec"] holds the vec1 vector
You can also easlly access elements like this:
myMap["vec"]//this will access the vector with the key "vec1"

You can create a vector to contain your vectors:
std::vector<std::vector<int>> my_vector_of_vectors;
// Add a vector
my_vector_of_vectors.push_back(std::vector<int>{});
// Add a number to the inner vector
my_vector_of_vectors[0].push_back(1);

you have a vector of vectors, vec[0] to vec[n], each one containing the vector.
However, this works est if you know the number of vectors (eg 10). If you need to add new ones on-demand, then a list of vectors or a map might be a better option for you.

Related

How to create vectors dynamically in C++

I am trying to initialize vectors depending upon user input. For example, if user provide n=4 then I have to create 4 vectors of varying sizes.
As for vectors syntax is :
vector<int> v1(x);
So, similarly I want to create v2,v3 and v4 named vectors.
I am confused. How can I do this ?
The names of individual vectors v1, v2, v3, ... are defined at compile time. If you want to have a dynamic number of vectors, you need a vector of vectors, e.g.:
std::vector<std::vector<int>> vs;
or if you already know the number of vectors n that you want:
std::vector<std::vector<int>> vs(n);
Then, instead of using v1, v2, v3, you'd use vs[0], vs[1], vs[2], and your code could use dynamically a vector v[i] where i is a variable or an expression.
You can add a vector to vs with emplace_back/push_back or resize:
vs.emplace_back();
//or
vs.push_back({});
// or
vs.push_back(std::vector<int>());
// or
vs.resize(4);
In the latter case vs will contain four empty vectors (or the first 4 existing vectors if vs already had more than 4 vectors).
And you can add elements to the inner vectors as usually, e.g.:
vs[0].push_back(42);
vs[2].resize(x);
After that the first vector will have length one and the third vector will have length x.
Or you can insert a vector with size x directly after the last vector:
vs.emplace_back(x);
// or
vs.push_back({x});
// or
vs.push_back(std::vector<int>(x));
Elements can then be accessed with double indices, e.g.
vs[1][14]
reads the 15th element of the 2nd vector.

how to push_back vector with no size in a specific location?

I'm trying to get a solid understanding of Vectors. So i understand if we init vectors as following we specify the exact location in array for the vector to exist
vector<int> temp[5];
temp[i].push_back(randomInt);(i a random position)
but what if i'm trying to have a vector without specified size because i do not know the amount of input? how would i define the first index for example of temp as i did previously using the following init?
vector<int> temp;
here:
vector<int> temp[5];
you declared an array of 5 vectors, but going by your description it looks like you're meant to declare one vector with pre-allocated 5 elements (if so, then it should have been like vector<int> temp(5);)
how would i define the first index for example of temp as i did
previously using the following init?
all the std containers have methods allowing you to push / emplace data (i.e. to extend them) and method size() allowing to check the current size of the container.

What's the difference between 2d vector and map of vector?

Let's say I've declared
map< int , vector<int> > g1;
vector< vector<int> > g2;
What are the similarities and dissimilarities between these two ?
The similarity is the way you access data, it can be the same syntax:
std::cout << g1[3][2] << std::endl;
std::cout << g2[3][2] << std::endl;
The main difference is the following: the map of vector doesn't have to contain all the indices. Then, you can have, as example, only 3 vectors in your map accessed with keys '17', '1234' and 13579 :
g2[17].resize(10);
g2[1234].resize(5);
g2[13579].resize(100);
If you want the same syntax with a vector of vectors, you need to have at least 13579 vectors (including 13576 empty vector) in your main vector. But this will use a lot of unused space in the memory.
Moreover, in your map, you also can access your vectors with negative keys (which is not possible in the vector of vectors):
g2[-10].resize(10);
After this obviously high difference, the storage of data is different. The vector allocates contiguous memory, while the map is stored as tree. The complexity of access in the vector is O(1), while it's O(log(n)) in the map. I invite you to learn some tutorial about containers in C++ to understand all the differences and the usual way to use them.
They are fundamentally different. While you may be able to do both g2[0] and g1[0], the behavior is vastly different. Assume there is nothing at index 0, then std::map will default construct a new value_type, in this case a vector, and return a reference, whereas std::vector has undefined behavior, but typically either segfaults or returns garbage.
They are also completely different in terms of memory layout. While std::map is backed by a red-black tree, std::vector is contiguous in memory. So inserting into the map will always result in dynamic allocation somewhere in memory, whereas the vector would be resized in case its current capacity is exceeded. Note however, that a vector of vectors is not contiguous in memory. The first vector, which itself is contiguous in memory is made up of vectors which look roughly like this in terms of data:
struct vector
{
T* data;
size_t capacity;
size_t size;
};
Where each of the vectors owns its dynamic memory allocation at data.
The advantage of the map is that is does not have to be densely populated, i.e. you can have something at index 0 and 12902 without all the stuff in between, plus it is sorted. If you don't need the sorted property and can use c++11 consider std::unordered_map. The vector is always densely populated, i.e. at size 10000, elements 0-9999 exist.
With example you can understand the difference. Lets say the vector<int> stores unique ids of people, and map stores respective pincode as key.
map< int , vector<int> > listOfPeopleAtRespectivePinCode;
vector< vector<int> > bunchOfGroupsOfPeople;
Evidently, map are capable to associate key and value (here a list of values), while vector can efficiently store a bunch of data.

Why can't we input a vector as we input an array in C++?

The wiki says:
The elements of a vector are stored contiguously. AND
Vectors allow random access; that is, an element of a vector may be referenced in the same manner as elements of arrays (by array indices).
So why can't we input the elements of a vector as:
vector<int> v;
for(int i=0;i<3;i++)
{
cin>>v[i];
}
Either you need to resize the vector upfront - as other answers say - or you can use C++ standard library. Then the equivalent of your for loop is the following one line:
copy_n(istream_iterator<int>(cin), 3, back_inserter(v));
and it takes care of allocation/resizing.
Your vector has zero elements right now. Try allocating it some space as:
vector<int> v(5);
Then your method would work.
The problem is that you need to allocate the elements of the vector first. So try vector<int> v(4);, so it will start with 4 elements. Then you can load values into them.

how to store vector of vector by index

Hi I have to store the below mentioned information in a vector of vectors format...
vector <vector <int>> ph;
vector<int> p, q;
p.push_back(1);
p.push_back(2);
p.push_back(3);
q.push_back(10);
q.push_back(20);
q.push_back(30);
q.push_back(40);
Now instead of using:
ph.push_back(p);
ph.push_back(q);
I want to use:
ph.at(0)=p
ph.at(1)=q
(This is the error that I am getting when I am using this: terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check)
The reason why I want to store it this way is....later I want to access the elements of a particular vector identified by its index i.e. 1 or 0.
For example I wish to access ph[0].size() i.e the size of p...identified by its index. That is, I want to perform the same operation as we are able to do in the case of simple arrays in c++ i.e. store the data in that array at a particular index and access the data from a particular index.
You are getting the error because when you instantiate the vector of vectors, it has size 0, and the at() method is allowed to do bound checks and raise an exception.
If you want to access by index like that then you are better off with an std::map or std::unordered_map. That makes the index independent of the order of insertion:
std::map<int, std::vector<int>> MapOfVectors;
std::vector<int> p, q;
// fill vectors
MapOfVectors[1] = q;
MapOfVectors[0] = p;
Otherwise, you would have to make sure your vector of vectors is large enough to insert elements by index:
// instantiate vector with size 2. You can insert p and q by index. (0, 1) only
vector<vector<int>> ph(2);
Or, resize it after creation:
vector<vector<int>> ph;
ph.resize(2);
When you define vector<vector<int>> ph the vector ph is empty. The .at() member function does bounds checking and correctly throws an exception when you try to write to non-existing elements.
You could do ph.resize(2) so that indices 0-1 would then be valid or just use push_back like you do currently.
I want to use:
ph.at(0)=p ph.at(1)=q
That attempts to access indices past the end of the array, hence the exception.
The reason why I want to store it this way is....later I want to access the elements of a particular vector identified by its index i.e. 1 or 0.
For example I wish to access ph[0].size() i.e the size of p...identified by its index. That is, I want to perform the same operation as we are able to do in the case of simple arrays in c++ i.e. store the data in that array at a particular index and access the data from a particular index.
You can achieve this by first filling the outer vector with empty inner vectors:
vector<vector<int> > ph(2);
Here, the 2 says to construct the outer vector to contain 2 default-constructed elements (themselves vector<int>).
Alternatively, you can use:
vector<vector<int> > ph;
ph.resize(2);
After you've done that, it will be safe to access the elements to store non-default-constructed values. That means the following won't throw:
ph.at(0)=p; ph.at(1)=q;