how to store vector of vector by index - c++

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;

Related

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.

Getting error while inputting value at 2d vector

I am using Codeblock to write c++ code. I was trying to input value at 2d vector. But it is getting an error. I am new at c++ and I have already searched at google but haven't found any solution. This is my code
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector <vector<double>> customar_data;
double value;
cin >> value;
customar_data[0][0].push_back(value);
cout >> customar_data[0][0];
return 0;
}
This is what codeblocks compiler showing
For the compiler's error, look at the types of the expressions involved.
customar_data is a vector <vector <double>>
customar_data[0] is a <vector <double>>
customar_data[0][0] is a double
The compiler complains when you request a member function (push_back) of the non-class type double.
For the logical error, look at what you are requesting. You start by constructing an empty vector (of vector<double>). Then you try to access the first element of this empty vector. You can avoid the need to specify the vector's size during construction, or you can access elements without adding them to the constructed vector, but you cannot do both. Vectors do not automatically increase in size as a result of accessing elements that had not existed.
The valid indices/subscripts to access are the non-negative integers less than the vector's size(). A default constructed vector starts with a size of zero, so there are no valid indices (you would need a non-negative integer less than zero). If you know how big you want the outermost vector to be when you construct it, you may want to specify that.
vector <vector<double>> customar_data(10);
// At this point, customar_data[0] through customar_data[9] can be used.
// Each of these elements is an empty vector of doubles.
If you do not know how big the outermost vector is going to be, you'll need to add each element before you use it. (This is intentionally singular; you can add an element, use it, then add another.)
vector <vector<double>> customar_data;
customar_data.push_back(vector<double>()); // Adds an empty vector as the first element.
customar_data[0].push_back(20.0); // Adds a value to the vector that is the first element.
// At this point, customar_data[0][0] is valid and has the value 20.0.
You might find that the emplace_back member function is more convenient than push_back, but let's go one step at a time.

Inserting elements into 2D vector

so I'm creating a class that implements an adjacency list. Currently in my class definition I initialized two vectors:
vector<vector<int>> adjList;
vector<int> neighbors;
and I declared two functions that I plan to use to make it:
bool constructAdjList();
bool insertIntoAdjList(int, int);
It's getting difficult wrapping my head around 2D vectors. I understand that it is essentially a vector of vectors, but I'm confused about how to insert a new value into one of the "subvectors". For example, I am able to create an adjacency list in createAdjList that is empty with the following loop:
for (int i = 0; i < numOfValues; i++){
neighbors.push_back(0);
adjList.push_back(neighbors);
neighbors.clear();
}
But how can I say, push_back the value 5 to the 4th vector in adjList, which would be represented in my insertIntoAdjList function as
insertIntoAdjList(4, 5);
I know I can access a specific value in a 2D vector by saying adjList[4][1], but how can I push one onto it?
Thanks!
To push on the vector that is an element of another vector, you simply do this
adjList[x].push_back();
If initially you do not have any values in the vector -
You can push values into one vector and then push this vector into the 2D vector.
For example:
vector< vector<int> > vt1;
vector<int> vt2;
vt2.push_back(value);
vt1.push_back(vt2);
If your vector is already populated then -
vt1[index].push_back(value);
A couple of notes here.
Your loop can be significantly shortened just be using the constructors of your two members:
vector<int> neighbors(1, 0); // set to length 1, value is zero
vector<vector<int>> adjList(numOfValues,neighbors); // "outer" vector is numOfValues long
. // each row is a *COPY* of neighbor
If you can't do this at construction time (maybe numOfValues isn't known yet), then there's still a better loop phrasing we can use:
// neighbors object can be reused
neighbors.clear(0);
neighbors.push_back(0);
adjList.reserve(numOfValues); // reserving memory ahead of time will prevent allocations
for (int i = 0; i < numOfValues; i++){
adjList.push_back(neighbors); // push_back is by *COPY*
}
In your example, by using clear and push_back to essentially build the same vector every loop iteration, you are risking an allocation and deallocation each iteration. In practice, most implementations won't do this, but if we can both shorten and potentially make things more efficient, we may as well.
Lastly, if the number of neighbors is relatively small and similar row to row (for instance a finite elements code with tetrahedral elements, where each element connects to ~5 others), then as others have suggested you may be better off with a different structure than vector-of-vector. For instance, a single vector that is logically organized such that a new "row" begins every N elements.

C++ vector: std::out_of_range Error

I have a structure in which I have a vector
vector<int> accept;
In my program , when I try to insert a value at a specific index. I get this error:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
In each iteration of my loop, I increment the AlphabetCounter and place a value at that specific index like the code given below :
AlphabetCounter=AlphabetCounter+1;
NewNextStateDouble.accept.at(AlphabetCounter)=1;
AlphabetCounter=-1 before starting the loop.
I don't get it why out of range error is occuring.
You can only grow a vector by using these two methods below:
Using the resize() method:
std::vector<int> my_vector;
v1.resize( 5 );
Using the push_back() method for dynamically increasing the size of the vector:
std::vector<int> my_vector;
for( int i = 0; i != 10; ++i )
{
my_vector.push_back( i );
}
std::cout << "The vector size is: " << my_vector.size() << std::endl;
In your situation, you have to know that subscripting does not add elements, as the standard says:
The subscript operator on vector (and string) fetches an existing
element; it does not add an element.
Also some recommendations about subscripting can be seen below.
Subscript Only Elements that are Known to Exist!
It is crucially important to understand that we may use the subscript operator
(the [] operator) to fetch only elements that actually exist. ( For example, see the code below )
It is an error to subscript an element that doesn’t exist, but it is an error that
the compiler is unlikely to detect. Instead, the value we get at run time is
undefined. (usually, an out_of_range exception)
Attempting to subscript elements that do not exist is, unfortunately, an
extremely common and pernicious programming error. So-called buffer
overflow errors are the result of subscripting elements that don’t exist. Such
bugs are the most common cause of security problems in PC and other
applications.
vector<int> ivec; // empty vector
cout << ivec[0]; // error: ivec has no elements!
vector<int> ivec2(10); // vector with ten elements
cout << ivec2[10]; // error: ivec2 has elements 0 . . . 9
You vector must have at least AlphabetCounter + 1 elements when you want to change a value at the position AlphabetCounter. You must make sure that is the case before you access the value.
std::vector does not grow to a specific index if the vector does not have enough elements. If you know the size (you need that to insert at a specific index) then you should resize() the vector to the appropriate size.
you have created an empty vector....use accept.push_back(5) ....
Description of push_back() method
Adds a new element at the end of the vector, after its current last element.
The content of val is copied (or moved) to the new element.
This effectively increases the container size by one, which causes an automatic reallocation of the allocated storage space if -and only if- the new vector size
surpasses the current vector capacity.

dynamically changing name of an array in 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.