vector< vector<int> >::iterator temp = mincost.end();
vector<int> a = *temp;
if ( *temp != *(temp--) )
return 0;
mincost is a 2d vector, I want to get the last vector<int> of this vector and last--.
I don't really understand about iterator :) . Help me !! :D
Thx ^^
minconst.end() points to the element one-past-the-end of the vector minconst; it doesn't point to the last element in the vector.
Since you want the last two elements, you should first test to be sure the vector actually has two elements in it, otherwise inevitably you'll run into problems. Then, accessing the last elements in the vector is simply a matter of *(minconst.end() - 1) and so forth.
The C++ Reference also has a description of iterators.
It would probably be helpful to learn about iterators in general.
A quick google search leads to many good references, not the least of which is
http://www.cppreference.com/wiki/stl/iterators
Good luck!
If you're new to STL containers, think of the end() iterator as something like the '\0' character in C-strings - they define where the end is, but the actual value they carry isn't useful. If you dereference the end iterator, you'll get junk, or most probably an exception.
Try this:
if (!mincost.empty())
{
//it contains atleast one 1-d vector and the 'end' iterator.
iter = mincost.end();
--iter;
//dereference iter here.
}
Once you're comfortable with thinking in terms of iterators, look up the reverse_iterator. As Effo mentioned, they are the best solution here.
Related
std::vector<int> vec={1,2,3};
std::vector<int>::iterator it = vec.begin();
if(vec == get_vec_from_it(it)){
puts('sucesss');
}
std::vector<int> get_vec_from_it(std::vector<int>::iterator it){
/*?*/
}
How should I write get_vec_from_it function in the above example?
The basic idea is that iterators abstract away where the elements come from, there might not even be a container. Afaik there is a single type of iterator that "knows" its container and that is std::back_insert_iterator, though thats an exception. The container member is only protected so there is even a way to get the container from a std::back_insert_iterator, but thats not how it is meant to be used.
You can adance the iterator to get the next element, but you wouldn't know where to stop, because at some point you'll reach the end of the vector and there is no way to identify it. If you pass begin and end you can create a copy of the original vector:
std::vector<int> get_vec_from_it(std::vector<int>::iterator begin ,std::vector<int>::iterator end){
return {begin,end};
}
Though, thats just a different way to copy the vector and you need to know both begin and end.
I made a function that returns the iterator that points to the node but I couldn't write the stop condition in a for statement. So I wonder if the stop condition can be written like it!=get_vec_from_it(it).end()
Functions that work on a range of elements typically take a pair of iterators, first and last, to know where to stop (alternatively a first iterator and number of elements can be used). Your idea of using it!=get_vec_from_it(it).end() is overcomplicating the issue. Just pass vec.end() to the function and use that: it != end.
No.
You can create a vector from a pair of iterators, or an iterator and number of elements. Example:
std::vector<int>
get_vec_from_its(std::vector<int>::iterator first, std::vector<int>::iterator last){
return std::vector<int>(first, last);
}
// ...
if(vec == get_vec_from_it(vec.begin(), vec.end())){
The function is of course so trivial that I would recommend instead to use the constructor directly.
I made a vector v which is [-5,-3]. I assigned an iterator iti to its beginning and then assigned another iterator itj as iti+1. Since my vector only has 2 elements, I would think that itj is recognized as the end of the vector or v.end(). But it is not.
Any ideas why that might be happening?
vector<int>v;
v.push_back(-5);
v.push_back(-3);
vector<int>::iterator iti, itj;
iti = v.begin();
itj = iti + 1;
if(itj==v.end())
cout << "1";
else
cout << "2";
Why does this print out '2' and not '1'?
end is an iterator to the (non-existing) element after the last element. iti + 2 would equal end because the vector has 2 elements. Generally, for a vector of size N: begin + N equals end.
The definition of vector:: end() is made in such a way that it returns the iterator which points to the (imaginary) element next to the last element.
Now, this might appear stupid initially, but is actually very useful, because, generally you use an iterator to iterate through a vector. And that is usually done using a for loop. So people do
for (vector<int>:: iterator i = v.begin();i!=v.end();i++)
which iterates over the whole vector.
Now I am not saying that we cannot achieve this if end returns an iterator to the last element. It is of course possible to do it, if we change the structure of our loop a little.
So, let us assume for a moment that end does return an iterator pointing to the last element. Now try to write a piece of code to iterate over the whole vector, say to print it. You will understand why the designers chose this kind of a convention. Remember that you cannot compare two iterators with <= like you do with normal integer indices.
BTW, it is the same convention for all STL containers.
because of not enough reputation I can't comment a post on the the thread:
How to get position of a certain element in strings vector, to use it as an index in ints vector?
I want to know something regarding this answer:
Original answer on thread:
To get a position of an element in a vector knowing an iterator pointing to the element, simply subtract v.begin() from the iterator:
ptrdiff_t pos = find(Names.begin(), Names.end(), old_name_) - Names.begin();
Now you need to check pos against Names.size() to see if it is out of bounds or not:
if(pos >= Names.size()) {
//old_name_ not found
}
vector iterators behave in ways similar to array pointers; most of what you know about pointer arithmetic can be applied to vector iterators as well.
Starting with C++11 you can use std::distance in place of subtraction for both iterators and pointers:
ptrdiff_t pos = distance(Names.begin(), find(Names.begin(), Names.end(), old_name_));
Questions:
How does this exactly work for the compiler? What happens in the background?
I know, that im passing two iterators to the find method, which seems logic: I pass the start and the end position. In between, I'm searching for the element. std::find() returns an iterator of the first element satisfying the value passed as third parameter to the std::find() method. So is std::distance doing nothing else than incrementing in a for loop something like a counter until it reaches the "end-point" iterator?
I could also write:
int index = distance(Names.begin(), find(Names.begin(), Names.end(), old_name_));
Why is it better to use ptrdiff_t than an integer? Someone commented in the original post that it lets you store the distance between any pair of iterators into the same container, even in situations when the result is negative. But I do not really get the point of it. Maybe you could explain that a bit further. (:
I'm coming from C#, where you can use something like (demonstrated on a string):
string test = "Hello World";
int index = test.IndexOf("d");
This seems a lot easier compared to the methods used above in C++. Is there something equivalent in C++?
Thank you very much for your help!
Best regards
I am trying to build a program that uses the second to last element in a vector, so far I've used:
(arr2.rbegin()+1)
If I use a comparison operator in a conditional such as:
if(arr2.rbegin()+1 == true)
I get an error message: no match for operator ==
Many of the answers and comments have the right idea but really ugly syntax. Here are two nice ways to express that.
arr2.end()[-2] // end() is past the last element, -1 for last element, -2 for second-last
arr2.rbegin()[1] // rbegin() is reverse order starting at 0 for last element, 1 for second-last
Demo: http://ideone.com/2cZeUq
It works because RandomAccessIterator, which vector has, is required to provide operator[] such that it[n] is equivalent to *(it + n), just like for pointers.
So the code in your question becomes just
if (arr2.rbegin()[1]) // test penultimate element
looking at the documentation here
http://www.cplusplus.com/reference/vector/vector/?kw=vector
I'd expect you to access your element by
secondToLast = myVector[myVector.size() - 2];
You can try doing like this:-
if(*(arr2.rbegin()+1))
Sometimes there might be less than 2 items in the list, so myVector.size() - 2 or other direct accessors will throw an error. I've done the following . . .
if (myVector.size() > 1)
{
secondToLast = myVector[myVector.size() - 2];
}
It depends on what you mean by "second to last element". Take the following iterator definition...
vector<int>::iterator it = arr2.end();
it--;
it--;
You have to decriment the iterator twice because when you declare the iterator to "point" to the end, it actually references the location AFTER the last element in the vector.
Dont forget that when you want the value that the iterator points to, you have to dereference it. like so...
cout << *it;
Mostly for lulz, but if your elements are non-scalar and you need to access a member of the element in question, you can use the ++-> construction:
std::vector<std::pair<int, int>> arr = ...;
auto grug = arr.rbegin()[1].first;
auto leet = arr.rbegin()++->first;
assert(grug == leet);
The way it works is we post-increment the iterator returned by rbegin() with ++ and then access it with ->. It is actually superior to the clearest [1] form in the sense it will work on any iterator, not only random access iterator.
Post it on review and get some popcorn.
There are many ways you can access elements from the back
one you can use is the back property that comes with std::vector container
and if you want to access an element from the back (either last element or up to n)
you can do this
std::vector vec{1,2,3};
int lastsecond = vec.back()-1; will give you -> 2;
you can check vector properties which there is a decent bit.
https://en.cppreference.com/w/cpp/container/vector
I have a method to which a vector's iterator is passed.
In this method I'd like to add some elements into the vector, but I am not sure whether this is possible when having only the iterator
void GUIComponentText::AddAttributes(vector<GUIComponentAttribute*>::iterator begin, vector<GUIComponentAttribute*>::iterator end)
{
for (vector<GUIComponentAttribute*>::iterator i = begin; i != end; ++i)
{
GUIComponentAttribute &attrib = *(*i);
// Here are the GUIComponentAttribute objects analyzed - if an object of a
// special kind appears, I would like to add some elements to the vector
}
}
Thanks
Markus
In the code you show, this is not possible. Especially because you should not add/remove elements to/from a vector while you iterate over it.
This is a long standing design "issue" in the STL. Iterators do not allow the modification of the structure of the underlying sequence they are iterating over: ie you can modify (sometimes) the elements themselves, but you cannot add/remove elements. Though InputIterator and OutputIterator are a bit special in this regard... hum...
This is actually the cause of the erase/remove idiom:
vec.erase(std::remove_if(vec.begin(), vec.end(), predicate), vec.end());
So, no, sorry, there is no way to actually modify the vector.
However, as exposed above, you can perfectly use the remove_if algorithm and simply return the new end of the valid range... or you can ask for the whole vector to begin with.
As noted by Björn, modifying a sequence structure while iterating over it is error-prone.
First, you'll have to change the interface. Given two iterators,
there's no way to get back to the container to which they refer; so if
you want to modify the container, you'll have to pass a reference to it,
i.e.:
void GUIComponentText::AddAttributes(
std::vector<GUIComponentAttribute*>& attributes )
{
for ( std::vector<GUIComponentAttribute*>::iter = attributes.begin();
iter != attributes.end();
++ iter )
{
// ...
}
}
Having done that: insertion can invalidate iterators. So it depends on
where you want to insert. If you want to insert at the current
position: std::vector<>::insert of a single element returns an
iterator to that element, which was inserted before your element, so you
can assign it to your iterator, adjust (if necessary), and continue:
iter = attributes.insert(iter, newAttribute);
++ iter; // Return to where we were...
If you're appending (push_back), the problem is a bit more complex;
you need to calculate the offset, then reconstruct the iterator:
size_t offset = iter - attributes.begin();
attributes.push_back( nweAttribute );
iter = attributes.begin() + offset;
In this case, it is probably simpler to iterate using a size_t and
[], rather than an iterator.
It is not possible to add elements into a vector whilst iterating over it. In addition, you most certainly cannot add one to a vector with just a pair of iterators- you'd need a pointer/reference to the whole vector object.
The best you could do is return a vector of new components to add by the the calling function.