c++ insert into vector at known position - c++

I wish to insert into a c++ vector at a known position. I know the c++ library has an insert() function that takes a position and the object to insert but the position type is an iterator. I wish to insert into the vector like I would insert into an array, using a specific index.

This should do what you want.
vector<int>myVec(3);
myVec.insert(myVec.begin() + INTEGER_OFFSET, DATA);
Please be aware that iterators may get invalidated when vector get reallocated. Please see this site.
EDIT: I'm not sure why the other answer disappeared...but another person mentioned something along the lines of:
myVec.insert(INDEX, DATA);
If I remember correctly, this should be just fine.

It's always nice to wrap these things up:
template <typename T>
T& insert_at(T& pContainer, size_t pIndex, const T::value_type& pValue)
{
pContainer.insert(pContainer.begin() + pIndex, pValue);
return pContainer;
}
That should do it. There is a now deleted answer that you can construct an iterator from an index, but I've never see that before. If that's true, that's definitely the way to go; I'm looking for it now.

Look at that debugging trace. The last thing that's executed is std::copy(__first=0x90c6fa8, __last=0x90c63bc, __result=0x90c6878). Looking back at what caused it, you called insert giving the position to insert at as 0x90c63bc. std::copy copies the range [first, last) to result, which must have room for last - first elements. This call has last < first, which is illegal (!), so I'm guessing that the position you're giving to insert at is wrong. Are you sure vnum hasn't underflowed somewhere along the line? In GDB with that trace showing, you should run
frame 10
print vnum
to check. In fact, if you haven't just abbreviated in your question, I've just found your bug. Your second line is:
new_mesh->Face(face_loc)->vertices.insert(vertices.begin()+vnum+1, new_vertices[j]);
It should have been:
new_mesh->Face(face_loc)->vertices.insert(new_mesg->Face(face_loc)->vertices.begin()+vnum+1, new_vertices[j]);
The first line gives the insertion point relative to the start of some other variable called vertices, not the one you want to insert into.

Related

Why using erase and unique function to remove duplicate vectors from a 2d vector is adding an extra empty vector in 2d vector?

I am using the below code to remove duplicate vectors from a 2d vector
sort(final_vec.begin(), final_vec.end());
final_vec.erase(unique(final_vec.begin(), final_vec.end()));
Can someone explain me why this is happening and what change should I make.
To make it clearer what exactly is going wrong, I'm going to introduce an intermediate variable to store the iterator returned by std::unique.
Your code is equivalent to:
sort(final_vec.begin(), final_vec.end());
auto new_ending_iterator = unique(final_vec.begin(), final_vec.end())
final_vec.erase(new_ending_iterator);
When we check the overloads of std::vector::erase, we see that this is actually the one-argument erase call:
iterator erase( const_iterator pos )
Removes the element at pos.
So this is erasing a single element from final_vec. However, our goal is to erase every element from new_ending_iterator all the way until final_vec.end(). To do so, we use the second overload of erase:
iterator erase( const_iterator first, const_iterator last );
Removes the elements in the range [first, last).
The correct code would therefore look like
sort(final_vec.begin(), final_vec.end());
auto new_ending_iterator = unique(final_vec.begin(), final_vec.end())
final_vec.erase(new_ending_iterator, final_vec.end());
Or, if you really want to keep it all in one line:
sort(final_vec.begin(), final_vec.end());
final_vec.erase(unique(final_vec.begin(), final_vec.end()), final_vec.end());
sort(final_vec.begin(), final_vec.end());
final_vec.erase(unique(final_vec.begin(), final_vec.end()));
I made changes in the second line and it worked for me.
Apparently, vector:erase has a several overloads: one to delete a single element and other to delete all elements in given rangr. I was using first one, which was wrong, but now, with a change, it's working for me.
Syntax for the correct overload of vector:erase and the solution for this error is below
sort(final_vec.begin(), final_vec.end());
final_vec.erase(unique(final_vec.begin(), final_vec.end()), final_vec.end());

C++ Vector.erase() last element corrupts iterator

I currently have a problem with vector.erase().
vector<gameObject> gameObjects;
for (auto it = gameObjects.end() - 1; it != gameObjects.begin();)
{
if ((it)->getDestroyed()) {
it = gameObjects.erase(it);
}
else {
--it;
}
}
So gameObject is the base class for everything inside the game and it has a bool flag that basically tells us if the object was destroyed. If the flag is set it should be removed from the vector.
class gameObject
{
protected:
bool toBeDestroyed;
public:
bool getDestroyed();
void markToDestroy();
};
Now the first destroyed object gets removed from the vector successfully and then I get get an error that iterator is not dereferencable, pointing to the vector library at line 73(?).
I then check with the msvc debugger. In the data preview it shows that iterator points to the last/newest element of gameObjects. It is then removed (erase(it)) and AFTERWARDS the data preview doesn't change and calling it->getDestroyed() results in the error message.
Debug assertion failed! vector iterator not dereferencible.
PS: I checked cplusplus.com and vector.erase should return a new, valid iterator so I'm not sure where I'm messing it up.
€: After I was told about the erase-remove idiom I went ahead and ended up with the following, which doesn't compile. Due to my function being a member of gameObject I'm not sure how to successfully call remove_if. Thanks
gameObjects.erase(remove_if(gameObjects.begin(), gameObjects.end(), gameObject::getDestroyed), gameObjects.end());
€2: A lot of you pointed out the first object isn't being checked. I propably should've pointed that out but the first element is ALWAYS the player and shouldn't be removed. Thanks for your comments nevertheless. I'll try with a simple forward loop without getting too fancy ^^.
€3: I tried Jonathan Mees suggested code but I get the exact same error message. I'll try and find out where exactly it happens but I can't just put a breakpoint into the erasing part anymore. Will mess around a bit.
€4: Problem was solved by removing the else {} condition and always decrementing the iterator. Thanks again for all your replies.
Let's say you have 2 objects in your vector and the last one is is marked as destroyed. When you call erase, it will return a new, valid iterator pointing at the element after the erased element. There is no element after the erased element, so the returned iterator is gameObjects.end(). You then continue to the top of the loop and dereference this iterator, which is not valid. You need to decrement your iterator after the erase if you want it pointing at a valid element.
One other note: If you ever wanted your first element removed, it will not be. Your loop exits when the iterator == gameObjects.begin(), so the first element is never checked.
Is there some reason you wanted to do this in reverse? If there is no specific reason, I would recommend you use the method recommended by #Borgleader.
Your loop is a little messed up - you're iterating backwards, ignoring the first element, and testing some elements multiple times. Might I suggest rbegin() as an alternative?
vector::erase returns the:
Iterator following the last removed element. If the iterator pos refers to the last element, the end() iterator is returned.
Meaning that vector::erase will never return vector::begin (unless you removed the only element in the container.) So it will always be dereferenced again after vector::erase is called. It will be dereferenced even if vector::end was returned by the call to vector::erase which is of course illegal.
Instead of this loop, consider using remove_if which is designed for this purpose:
gameObjects.erase(remove_if(begin(gameObjects),
end(gameObjects),
[](const auto& i){ return i.getDestroyed(); }), end(gameObjects));
EDIT:
I noticed you try to use this in your edit. You cannot use a bare function pointer as the predicate. If you want to avoid a lambda, you should consider the use of mem_fn:
gameObjects.erase(remove_if(begin(gameObjects),
end(gameObjects),
mem_fn(&gameObject::getDestroyed)), end(gameObjects));
Live Example
If there's difficulty in reading that line feel free to use as many variable as you like:
auto p = mem_fn(&gameObject::getDestroyed);
auto result = remove_if(begin(gameObjects), end(gameObjects), p);
gameObjects.erase(result, end(gameObjects));

C++ Generate Permutations of a set recursively

I've been assigned the task of writing a C++ function that returns all possible permutations from a group of integers. I've done a bit of research but all algorithms I find show the permutation being printed out.
The problem I'm running in to is I don't know how to set up the function, specifically, how I should handle receiving data from recursive calls. My first guess was to use a linked list, but I know if I try to return a pointer to a Node I'll end up with a pointer to invalid memory.
My other guess was to use some sort of global linked list of vectors, but I can't imagine how I could add to the linked list from a function itself. Further, this is more sidestepping the problem than actually solving it, and I'd like to actually solve it if at all possible.
As this is a homework problem, I don't expect anyone to hand me an answer outright. I'm just lost and would greatly appreciate someone pointing me in the right direction.
You could use std::next_permutation. It operates on the data structure so you can do anything you want with the data structure after each iteration.
If you're implementing your own permutation logic, suppose you're operating on vector<int>& data, you could add a parameter like vector<vector<int> >& result in your recursive function. Each time a permutation is generated you could simply do result.push_back(data).
One possible approach: store the set in an array, then call a function giving it an array (a ptr to the first item) and the array length as parameters. Make sure the array is initially sorted, say in ascending order, then reorder it to a 'lexically next' permutation on each call.
You can use next_permutation and accumulate copies of all the permutations:
template<class T>
vector<vector<T>> permutations(vector<T> input) {
vector<vector<T>> result{input};
while (next_permutation(begin(input), end(input)))
result.push_back(input);
return result;
}
Since this is a homework problem, I expect you have to generate the permutations yourself. But this points to an approach—have an accumulator of type vector<vector<T>>, and pass it as a reference parameter to the recursive version of your algorithm:
template<class T>
vector<vector<T>> permutations(const vector<T>& input) {
vector<vector<T>> output;
collect_permutations(input, output);
return output;
}
template<class T>
void collect_permutations(const vector<T>& input, vector<vector<T>>& output) {
// Instead of printing, simply write to output using push_back() etc.
}
If you in fact want just the combinations (order of the items in the returned set doesn't matter), then I would use the binary counter approach - for a source set of N items, define an N-bit binary counter and count from 0 to 2^N-1 - each bit in the counter corresponds to one of the N items, and each number represents a combination where only the items that have a 1 bit are present in the combination.
For permutations, you would then have to generate all possible orderings of the items in each individual combination, along with some way to eliminate duplicates if necessary.

Remove element from vector error C++

I know this might seem as a duplicate question, but it is not, I have a problem with a function and don''t know why it behaves like that.
I have a vector which holds elements of type MyMaterial** (std::vector). At a point in my program, I will know an element, "currentElement", and I will want to remove it.
I tried doing this:
myMaterials.erase(currentElement);
But here is the problem: Instead of only deleting "currentElement", it also deletes all elements added after it. Why does it do that and how can I solve it?
I must mention that I don''t know the position of "currentElement" in the vector, and i prefere not to search for it, I''m hoping there is another way.
If you are using std::vector, then:
Erase elements Removes from the vector either a single element
(position) or a range of elements ([first,last)).
Maybe you are looking for something like this:
How do I remove an item from a stl vector with a certain value?
To use vector::erase(iterator) to remove an element from a vector, you may either have to know its index OR iterate thru the list to hunt for it.
Luckily, There is the std::map, and this is how you would work it
std::map<std::string,myMaterial> myMaterials;
myMaterial mat;//assuming it doesnt take any args
myMaterials['myMaterialXYZ'] = mat; ///add it to the array
myMaterials.erase('myMaterialXYZ'); ///Erase by key..(or "name" in this case)
Now you can easily track string names instead of ever changing index positions...and memory locations, which by the way may be another ace up your sleeve.
I couldn''t really use the examples given by you above, because I got all kinds of errors, due to the type of elements the vector holds. But I made a function which managed to delete the specific element:
int i=0;
int found=0;
MyMaterial **material = gMaterials.begin();
while(material != gMaterials.end() && found == 0)
{
if(currentElement == material)
{
gMaterials.erase(gMaterials.begin() + i, gMaterials.begin() + i+1);
found = 1;
}
i++;
cloth++;
}
I don''t know how good/correct it is, but it does the job.
Thank you very much for the suggestions and the help.

iterator for strings in array

i have the following situation
typedef std::array<std::array<string,9>,9>candidates;
std::vector<candidates>cand;
i need to traverse the strings in depths of recursion and want them unaltered even with re-sizing. how do i do it? the iterators i was using previously get invalidated on re-sizing i want a way around.. here's the previous attempt.
for(itr[d] = cand[d][i][j].begin(); itr[d] !=cand[d][i][j].end(); ++itr[d])
{
//if condition met - proceed to recursive call
//else reset (using ppp and push) and proceed to next element of string
}
Have you tried
func(*(itr[d]));
The dereference operator takes precedence over the indexing operator.